﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Media;
using System.Diagnostics;
using System.Windows.Forms;
using SoftFX.Extended;
using System.Globalization;
using System.Threading;
using System.Reflection;
using SoftFX.Basic;

namespace Mql2Fdk
{
	/// <summary>
	/// 
	/// </summary>
	public class MqlAdapter
	{
		#region constants

		#region color constants

		/// <summary>
		/// Blue color constant.
		/// </summary>
		protected static int Blue = KnownColor.Blue.KnownToArgb();

		/// <summary>
		/// White color constant.
		/// </summary>
		protected static int White = CastUtils.KnownToArgb(KnownColor.White);

		/// <summary>
		/// Red color constant.
		/// </summary>
		protected static int Red = CastUtils.KnownToArgb(KnownColor.Red);

		/// <summary>
		/// DarkGray constant.
		/// </summary>
		protected static int DarkGray = CastUtils.KnownToArgb(KnownColor.DarkGray);

		/// <summary>
		/// Orange constant.
		/// </summary>
		protected static int Orange = CastUtils.KnownToArgb(KnownColor.Orange);

		/// <summary>
		/// Violet constant.
		/// </summary>
		protected static int Violet = CastUtils.KnownToArgb(KnownColor.Violet);

		/// <summary>
		/// Green constant.
		/// </summary>
		protected static int Green = CastUtils.KnownToArgb(KnownColor.Green);

		/// <summary>
		/// Yellow color.
		/// </summary>
		protected static int Yellow = CastUtils.KnownToArgb(KnownColor.Yellow);

		/// <summary>
		/// Purple color.
		/// </summary>
		protected static int Purple = CastUtils.KnownToArgb(KnownColor.Purple);

		/// <summary>
		/// Lime color
		/// </summary>
		protected static int Lime = CastUtils.KnownToArgb(KnownColor.Lime);

		/// <summary>
		/// Pink color
		/// </summary>
		protected static int Pink = KnownColor.Pink.KnownToArgb();

		/// <summary>
		/// Aqua color
		/// </summary>
		protected static int Aqua = KnownColor.Aqua.KnownToArgb();

		/// <summary>
		/// DarkOrange
		/// </summary>
		protected static int DarkOrange = KnownColor.DarkOrange.KnownToArgb();

		/// <summary>
		/// DarkBlue
		/// </summary>
		protected static int DarkBlue = KnownColor.DarkBlue.KnownToArgb();

		/// <summary>
		/// Chocolate
		/// </summary>
		protected static int Chocolate = KnownColor.Chocolate.KnownToArgb();

		/// <summary>
		/// Maroon
		/// </summary>
		protected static int Maroon = KnownColor.Maroon.KnownToArgb();

		/// <summary>
		/// Teal
		/// </summary>
		protected static int Teal = KnownColor.Teal.KnownToArgb();

		/// <summary>
		/// LimeGreen
		/// </summary>
		protected static int LimeGreen = KnownColor.LimeGreen.KnownToArgb();

		/// <summary>
		/// LightGreen
		/// </summary>
		protected static int LightGreen = KnownColor.LightGreen.KnownToArgb();

		/// <summary>
		/// Tomato
		/// </summary>
		protected static int Tomato = KnownColor.Tomato.KnownToArgb();

		/// <summary>
		/// Black
		/// </summary>
		protected static int Black = KnownColor.Black.KnownToArgb();

		/// <summary>
		/// Brown
		/// </summary>
		protected static int Brown = KnownColor.Brown.KnownToArgb();

		/// <summary>
		/// 
		/// </summary>
		protected static int DarkViolet = KnownColor.Tomato.KnownToArgb();

		/// <summary>
		/// 
		/// </summary>
		protected static int DeepPink = KnownColor.Tomato.KnownToArgb();

		/// <summary>
		/// DodgerBlue
		/// </summary>
		protected static int DodgerBlue = KnownColor.DodgerBlue.KnownToArgb();

		/// <summary>
		/// Gold
		/// </summary>
		protected static int Gold = KnownColor.Gold.KnownToArgb();

		/// <summary>
		/// LawnGreen
		/// </summary>
		protected static int LawnGreen = KnownColor.LawnGreen.KnownToArgb();

		/// <summary>
		/// MediumBlue
		/// </summary>
		protected static int MediumBlue = KnownColor.MediumBlue.KnownToArgb();

		/// <summary>
		/// MediumSeaGreen
		/// </summary>
		protected static int MediumSeaGreen = KnownColor.MediumSeaGreen.KnownToArgb();

		/// <summary>
		/// OrangeRed
		/// </summary>
		protected static int OrangeRed = KnownColor.OrangeRed.KnownToArgb();

		/// <summary>
		/// RoyalBlue
		/// </summary>
		protected static int RoyalBlue = KnownColor.RoyalBlue.KnownToArgb();


		/// <summary>
		/// No color constant.
		/// </summary>
		protected const int CLR_NONE = -1;

		#endregion

		#region price constants

		/// <summary>
		/// Close price.
		/// </summary>
		protected const int PRICE_CLOSE = 0;

		/// <summary>
		/// Open price.
		/// </summary>
		protected const int PRICE_OPEN = 1;

		/// <summary>
		/// High price.
		/// </summary>
		protected const int PRICE_HIGH = 2;

		/// <summary>
		/// Low price.
		/// </summary>
		protected const int PRICE_LOW = 3;

		/// <summary>
		/// Median price, (high+low)/2. 
		/// </summary>
		protected const int PRICE_MEDIAN = 4;

		/// <summary>
		///  Typical price, (high+low+close)/3.
		/// </summary>
		protected const int PRICE_TYPICAL = 5;

		/// <summary>
		///  Weighted close price, (high+low+close+close)/4. 
		/// </summary>
		protected const int PRICE_WEIGHTED = 6;

		#endregion

		#region time frame constants

		/// <summary>
		/// 1 minute
		/// </summary>
		protected const int PERIOD_M1 = 1;

		/// <summary>
		/// 5 minutes
		/// </summary>
		protected const int PERIOD_M5 = 5;

		/// <summary>
		/// 15 minutes
		/// </summary>
		protected const int PERIOD_M15 = 15;

		/// <summary>
		/// 30 minutes
		/// </summary>
		protected const int PERIOD_M30 = 30;

		/// <summary>
		/// 1 hour
		/// </summary>
		protected const int PERIOD_H1 = 60;

		/// <summary>
		/// 4 hour
		/// </summary>
		protected const int PERIOD_H4 = 240;

		/// <summary>
		/// Daily
		/// </summary>
		protected const int PERIOD_D1 = 1440;

		/// <summary>
		/// Weekly
		/// </summary>
		protected const int PERIOD_W1 = 10080;

		/// <summary>
		/// Monthly
		/// </summary>
		protected const int PERIOD_MN1 = 43200;

		#endregion

		#region moving Average methods

		/// <summary>
		/// Simple moving average.
		/// </summary>
		protected const int MODE_SMA = 0;

		/// <summary>
		/// Exponential moving average.
		/// </summary>
		protected const int MODE_EMA = 1;

		/// <summary>
		/// Smoothed moving average.
		/// </summary>
		protected const int MODE_SMMA = 2;

		/// <summary>
		/// Linear weighted moving average.
		/// </summary>
		protected const int MODE_LWMA = 3;

		/// <summary>
		/// MODE_GATORTEETH constant
		/// </summary>
		protected const int MODE_GATORTEETH = 2;

		/// <summary>
		/// Calculates the Bill Williams' Accelerator/Decelerator oscillator. 
		/// </summary>
		/// <param name="symbol">Symbol name of the security on the data of which the indicator will be calculated. NULL means the current symbol.</param>
		/// <param name="timeframe">Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe.</param>
		/// <param name="shift">Index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago).</param>
		/// <returns></returns>
		protected double iAC(string symbol, int timeframe, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Movement directional index and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="applied_price"></param>
		/// <param name="mode"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iADX(string symbol, int timeframe, int period, int applied_price, int mode, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Bill Williams' Alligator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="jaw_period"></param>
		/// <param name="jaw_shift"></param>
		/// <param name="teeth_period"></param>
		/// <param name="teeth_shift"></param>
		/// <param name="lips_period"></param>
		/// <param name="lips_shift"></param>
		/// <param name="ma_method"></param>
		/// <param name="applied_price"></param>
		/// <param name="mode"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iAlligator(string symbol, int timeframe, int jaw_period, int jaw_shift, int teeth_period,
		                            int teeth_shift, int lips_period, int lips_shift, int ma_method, int applied_price,
		                            int mode, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Indicator of the average true range and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iATR(string symbol, int timeframe, int period, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Bill Williams' Awesome oscillator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iAO(string symbol, int timeframe, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Fractals and returns its value
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="mode"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iFractals(string symbol, int timeframe, int mode, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Moving average indicator and returns its value. 
		/// </summary>
		/// <param name="symbol">Symbol the data of which should be used to calculate indicator. NULL means the current symbol.</param>
		/// <param name="timeframe">Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe</param>
		/// <param name="period">Averaging period for calculation.</param>
		/// <param name="ma_shift">MA shift. Indicators line offset relate to the chart by timeframe.</param>
		/// <param name="ma_method">MA method. It can be any of the Moving Average method enumeration value.</param>
		/// <param name="applied_price">Applied price. It can be any of Applied price enumeration values.</param>
		/// <param name="shift">Index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago).</param>
		/// <returns>Moving average indicator</returns>
		protected double iMA(string symbol, int timeframe, int period, int ma_shift, int ma_method, int applied_price,
		                     int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Moving averages convergence/divergence and returns its value. In the systems where OsMA 
		/// is called MACD Histogram, this indicator is displayed as two lines.
		/// In the Client Terminal, the Moving Average Convergence/Divergence is drawn as a histogram. 
		/// </summary>
		/// <param name="symbol">Symbol the data of which should be used to calculate indicator. NULL means the current symbol</param>
		/// <param name="timeframe">Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe.</param>
		/// <param name="fast_ema_period">Number of periods for fast moving average calculation.</param>
		/// <param name="slow_ema_period">Number of periods for slow moving average calculation.</param>
		/// <param name="signal_period">Number of periods for signal moving average calculation.</param>
		/// <param name="applied_price">Applied price. It can be any of Applied price enumeration values.</param>
		/// <param name="mode">Indicator line index. It can be any of the Indicators line identifiers enumeration value.</param>
		/// <param name="shift">Index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago).</param>
		/// <returns></returns>
		protected double iMACD(string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period,
		                       int applied_price, int mode, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Money flow index and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iMFI(string symbol, int timeframe, int period, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Momentum indicator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="applied_price"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iMomentum(string symbol, int timeframe, int period, int applied_price, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Moving Average of Oscillator and returns its value. Sometimes called MACD Histogram in some systems. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="fast_ema_period"></param>
		/// <param name="slow_ema_period"></param>
		/// <param name="signal_period"></param>
		/// <param name="applied_price"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iOsMA(string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period,
		                       int applied_price, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Relative strength index and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="applied_price"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iRSI(string symbol, int timeframe, int period, int applied_price, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Parabolic Stop and Reverse system and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="step"></param>
		/// <param name="maximum"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iSAR(string symbol, int timeframe, double step, double maximum, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Stochastic oscillator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="Kperiod"></param>
		/// <param name="Dperiod"></param>
		/// <param name="slowing"></param>
		/// <param name="method"></param>
		/// <param name="price_field"></param>
		/// <param name="mode"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iStochastic(string symbol, int timeframe, int Kperiod, int Dperiod, int slowing, int method,
		                             int price_field, int mode, int shift)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Calculates the Larry William's percent range indicator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iWPR(string symbol, int timeframe, int period, int shift)
		{
			throw new NotImplementedException();
		}

		#endregion

		#region Indicators

		/// <summary>
		/// The function returns the amount of bars not changed after the indicator had been launched last. The most calculated bars do not need any recalculation. In most cases, same count of index values do not need for recalculation. The function is used to optimize calculating.
		/// Note: The latest bar is not considered to be calculated and, in the most cases, it is necessary to recalculate only this bar. However, there occur some boundary cases where custom indicator is called from the expert at the first tick of the new bar. It is possible that the last tick of the previous bar had not been processed (because the last-but-one tick was being processed when this last tick came), the custom indicator was not called and it was not calculated because of this. To avoid indicator calculation errors in such situations, the IndicatorCounted() function returns the count of bars minus one. 
		/// </summary>
		/// <returns></returns>
		protected int IndicatorCounted()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sets precision format (the count of digits after decimal point) to visualize indicator values. The symbol price preicision is used by default, the indicator being attached to this symbol chart. 
		/// </summary>
		/// <param name="digits"></param>
		protected void IndicatorDigits(int digits)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sets precision format (the count of digits after decimal point) to visualize indicator values. The symbol price preicision is used by default, the indicator being attached to this symbol chart. 
		/// </summary>
		/// <param name="digits"></param>
		protected void SetIndexDrawBegin(int index, int begin)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sets the "short" name of a custom indicator to be shown in the DataWindow and in the chart subwindow. 
		/// </summary>
		/// <param name="name"></param>
		protected void IndicatorShortName(string name)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Allocates memory for buffers used for custom indicator calculations. The amount of buffers cannot exceed 8 or be less than the value given in the indicator_buffers property. If custom indicator requires additional buffers for counting, this function must be used for specifying of the total amount of buffers. 
		/// </summary>
		/// <param name="count"></param>
		protected void IndicatorBuffers(int count)
		{
			throw new NotImplementedException();
		}

		#endregion

		#region Indexes

		/// <summary>
		/// Binds the array variable declared at a global level to the custom indicator pre-defined buffer. The amount of buffers needed to calculate the indicator is set with the IndicatorBuffers() function and cannot exceed 8. If it succeeds, TRUE will be returned, otherwise, it will be FALSE. To get the extended information about the error, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="array"></param>
		/// <returns></returns>
		protected bool SetIndexBuffer(int index, double[] array)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sets drawing line description for showing in the DataWindow and in the tooltip. 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="text"></param>
		protected void SetIndexLabel(int index, string text)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sets offset for the drawing line. For positive values, the line drawing will be shifted to the right, otherwise it will be shifted to the left. I.e., the value calculated on the current bar will be drawn shifted relatively to the current bar. 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="shift"></param>
		protected void SetIndexShift(int index, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sets offset for the drawing line. For positive values, the line drawing will be shifted to the right, otherwise it will be shifted to the left. I.e., the value calculated on the current bar will be drawn shifted relatively to the current bar. 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="shift"></param>
		protected void SetIndexStyle(int index, int type, int style = EMPTY, int width = EMPTY, color clr = default(color))
		{
			throw new NotImplementedException();
		}

		#endregion


		#region Windows

		/// <summary>
		/// Returns name of the executed expert, script, custom indicator, or library, depending on the MQL4 program, from which this function has been called. 
		/// </summary>
		/// <returns></returns>
		protected string WindowExpertName()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// If indicator with name was found, the function returns the window index containing this specified indicator, otherwise it returns -1.
		/// Note: WindowFind() returns -1 if custom indicator searches itself when init() function works. 
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		protected int WindowFind(string name)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns maximal value of the vertical scale of the specified subwindow of the current chart (0-main chart window, the indicators' subwindows are numbered starting from 1). If the subwindow index has not been specified, the maximal value of the price scale of the main chart window is returned.
		/// See also WindowPriceMin(), WindowFirstVisibleBar(), WindowBarsPerChart() 
		/// </summary>
		/// <param name="index"></param>
		/// <returns></returns>
		protected double WindowPriceMax(int index = 0)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns minimal value of the vertical scale of the specified subwindow of the current chart (0-main chart window, the indicators' subwindows are numbered starting from 1). If the subwindow index has not been specified, the minimal value of the price scale of the main chart window is returned.
		/// See also WindowPriceMax(), WindowFirstVisibleBar(), WindowBarsPerChart() 
		/// </summary>
		/// <param name="index"></param>
		/// <returns></returns>
		protected double WindowPriceMin(int index = 0)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Saves current chart screen shot as a GIF file. Returns FALSE if it fails. To get the error code, one has to use the GetLastError() function.
		/// The screen shot is saved in the terminal_dir\experts\files (terminal_dir\tester\files in case of testing) directory or its subdirectories. 
		/// </summary>
		/// <param name="filename"></param>
		/// <param name="size_x"></param>
		/// <param name="size_y"></param>
		/// <param name="start_bar"></param>
		/// <param name="chart_scale"></param>
		/// <param name="chart_mode"></param>
		/// <returns></returns>
		protected bool WindowScreenShot(string filename, int size_x, int size_y, int start_bar = -1, int chart_scale = -1,
		                                int chart_mode = -1)
		{
			throw new NotImplementedException();
		}

		#endregion

		#region market info constants

		/// <summary>
		/// Last incoming bid price. For the current symbol, it is stored in the predefined variable Bid
		/// </summary>
		protected const int MODE_BID = 9;

		/// <summary>
		/// Last incoming ask price. For the current symbol, it is stored in the predefined variable Ask
		/// </summary>
		protected const int MODE_ASK = 10;

		/// <summary>
		/// Point size in the quote currency. For the current symbol, it is stored in the predefined variable Point
		/// </summary>
		protected const int MODE_POINT = 11;

		/// <summary>
		/// Count of digits after decimal point in the symbol prices. For the current symbol, it is stored in the predefined variable Digits
		/// </summary>
		protected const int MODE_DIGITS = 12;

		/// <summary>
		///  Spread value in points
		/// </summary>
		protected const int MODE_SPREAD = 13;

		/// <summary>
		/// Lot size in the base currency.
		/// </summary>
		protected const int MODE_LOTSIZE = 15;

		/// <summary>
		/// Tick size in the quote currency.
		/// </summary>
		protected const int MODE_TICKSIZE = 17;

		/// <summary>
		///  Swap of the long position.
		/// </summary>
		protected const int MODE_SWAPLONG = 18;

		/// <summary>
		/// Swap of the short position.
		/// </summary>
		protected const int MODE_SWAPSHORT = 19;

		/// <summary>
		/// Minimum permitted amount of a lot
		/// </summary>
		protected const int MODE_MINLOT = 23;

		/// <summary>
		/// Step for changing lots
		/// </summary>
		protected const int MODE_LOTSTEP = 24;

		/// <summary>
		/// Maximum permitted amount of a lot
		/// </summary>
		protected const int MODE_MAXLOT = 25;

		/// <summary>
		/// Margin calculation mode. 0 - Forex; 1 - CFD; 2 - Futures; 3 - CFD for indices.
		/// </summary>
		protected const int MODE_MARGINCALCMODE = 28;

		/// <summary>
		/// Initial margin requirements for 1 lot.
		/// </summary>
		protected const int MODE_MARGININIT = 29;

		/// <summary>
		/// Stop level
		/// </summary>
		protected const int MODE_STOPLEVEL = 30;

		/// <summary>
		/// Tick value
		/// </summary>
		protected const int MODE_TICKVALUE = 31;

		/// <summary>
		/// Starting mode
		/// </summary>
		protected const int MODE_STARTING = 32;

		/// <summary>
		/// Expiration mode
		/// </summary>
		protected const int MODE_EXPIRATION = 33;

		/// <summary>
		/// Trading is allowed
		/// </summary>
		protected const int MODE_TRADEALLOWED = 34;

		/// <summary>
		/// Trading is allowed
		/// </summary>
		protected const int MODE_MAIN = 35;

		#endregion

		#region Object properties

		/// <summary>
		/// Datetime value to set/get first coordinate time part.
		/// </summary>
		protected datetime OBJPROP_TIME1 = new datetime(0);

		/// <summary>
		/// Double value to set/get first coordinate price part.
		/// </summary>
		protected double OBJPROP_PRICE1;

		/// <summary>
		/// Datetime value to set/get second coordinate time part.
		/// </summary>
		protected datetime OBJPROP_TIME2 = new datetime(0);

		/// <summary>
		/// Double value to set/get second coordinate price part.
		/// </summary>
		protected double OBJPROP_PRICE2 = new datetime(0);

		/// <summary>
		/// Datetime value to set/get third coordinate time part.
		/// </summary>
		protected datetime OBJPROP_TIME3 = new datetime(0);

		/// <summary>
		/// Double value to set/get third coordinate price part.
		/// </summary>
		protected double OBJPROP_PRICE3 = new datetime(0);

		/// <summary>
		/// Color value to set/get object color.
		/// </summary>
		protected color OBJPROP_COLOR = new color(0);

		/// <summary>
		/// Value is one of STYLE_SOLID, STYLE_DASH, STYLE_DOT, STYLE_DASHDOT, STYLE_DASHDOTDOT constants to set/get object line style.
		/// </summary>
		protected int OBJPROP_STYLE = new datetime(0);

		/// <summary>
		/// Integer value to set/get object line width. Can be from 1 to 5.
		/// </summary>
		protected int OBJPROP_WIDTH = new datetime(0);

		/// <summary>
		/// Boolean value to set/get background drawing flag for object.
		/// </summary>
		protected bool OBJPROP_BACK;

		/// <summary>
		/// Boolean value to set/get ray flag of object.
		/// </summary>
		protected bool OBJPROP_RAY;

		/// <summary>
		/// Boolean value to set/get ellipse flag for fibo arcs.
		/// </summary>
		protected bool OBJPROP_ELLIPSE;

		/// <summary>
		/// Double value to set/get scale object property.
		/// </summary>
		protected datetime OBJPROP_SCALE = new datetime(0);

		/// <summary>
		/// Double value to set/get angle object property in degrees.
		/// </summary>
		protected datetime OBJPROP_ANGLE = new datetime(0);

		/// <summary>
		/// Integer value or arrow enumeration to set/get arrow code object property.
		/// </summary>
		protected datetime OBJPROP_ARROWCODE = new datetime(0);

		/// <summary>
		/// Value can be one or combination (bitwise addition) of object visibility constants to set/get timeframe object property.
		/// </summary>
		protected datetime OBJPROP_TIMEFRAMES = new datetime(0);

		/// <summary>
		/// Double value to set/get deviation property for Standard deviation objects.
		/// </summary>
		protected datetime OBJPROP_DEVIATION = new datetime(0);

		/// <summary>
		/// Integer value to set/get font size for text objects.
		/// </summary>
		protected datetime OBJPROP_FONTSIZE = new datetime(0);

		/// <summary>
		/// Integer value to set/get anchor corner property for label objects. Must be from 0-3.
		/// </summary>
		protected datetime OBJPROP_CORNER = new datetime(0);

		/// <summary>
		/// Integer value to set/get anchor X distance object property in pixels.
		/// </summary>
		protected datetime OBJPROP_XDISTANCE = new datetime(0);

		/// <summary>
		/// Integer value is to set/get anchor Y distance object property in pixels.
		/// </summary>
		protected datetime OBJPROP_YDISTANCE = new datetime(0);


		/// <summary>
		/// Vertical line. Uses price part of first coordinate..
		/// </summary>
		protected int OBJ_VLINE = 0;

		/// <summary>
		/// Horizontal line. Uses price part of first coordinate..
		/// </summary>
		protected int OBJ_HLINE = 1;

		/// <summary>
		/// Text label. Uses 1 coordinate in pixels. 
		/// </summary>
		protected int OBJ_LABEL = 23;

		/// <summary>
		/// Text. Uses 1 coordinate.
		/// </summary>
		protected int OBJ_TEXT = 21;

		/// <summary>
		/// Arrows. Uses 1 coordinate.
		/// </summary>
		protected int OBJ_ARROW = 22;


		#endregion

		#region constants

		/// <summary>
		/// index in the order pool
		/// </summary>
		protected const int SELECT_BY_POS = 0;

		/// <summary>
		/// index is order ticket
		/// </summary>
		protected const int SELECT_BY_TICKET = 1;

		/// <summary>
		/// order selected from trading pool(opened and pending orders)
		/// </summary>
		protected const int MODE_TRADES = 0;

		/// <summary>
		/// order selected from history pool (closed and canceled order)
		/// </summary>
		protected const int MODE_HISTORY = 1;

		/// <summary>
		/// buying position
		/// </summary>
		protected const int OP_BUY = 0;

		/// <summary>
		/// selling position
		/// </summary>
		protected const int OP_SELL = 1;

		/// <summary>
		/// buy limit pending position
		/// </summary>
		protected const int OP_BUYLIMIT = 2;

		/// <summary>
		/// buy stop pending position
		/// </summary>
		protected const int OP_BUYSTOP = 3;

		/// <summary>
		/// sell limit pending position
		/// </summary>
		protected const int OP_SELLLIMIT = 4;

		/// <summary>
		/// sell stop pending position.
		/// </summary>
		protected const int OP_SELLSTOP = 5;

		#endregion

		#region common constants

		/// <summary>
		/// Used with array functions. Indicates that all array elements will be processed.
		/// </summary>
		protected const int WHOLE_ARRAY = 0;

		#endregion

		#region mode constants

		/// <summary>
		/// Open price.
		/// </summary>
		protected const int MODE_OPEN = 0;

		/// <summary>
		/// Low price.
		/// </summary>
		protected const int MODE_LOW = 1;

		/// <summary>
		/// High price.
		/// </summary>
		protected const int MODE_HIGH = 2;

		/// <summary>
		/// Close price.
		/// </summary>
		protected const int MODE_CLOSE = 3;

		/// <summary>
		/// Volume, used in iLowest() and iHighest() functions.
		/// </summary>
		protected const int MODE_VOLUME = 4;

		/// <summary>
		/// Bar open time, used in ArrayCopySeries() function.
		/// </summary>
		protected const int MODE_TIME = 5;

		/// <summary>
		/// MODE_FREEZELEVEL constant
		/// </summary>
		protected const int MODE_FREEZELEVEL = 33;

		/// <summary>
		/// MODE_GATORJAW constant
		/// </summary>
		protected const int MODE_GATORJAW = 1;

		/// <summary>
		/// MODE_LOWER constant
		/// </summary>
		protected const int MODE_LOWER = 2;

		/// <summary>
		/// MODE_GATORLIPS constant
		/// </summary>
		protected const int MODE_GATORLIPS = 3;

		/// <summary>
		/// MODE_MARGINREQUIRED constant
		/// </summary>
		protected const int MODE_MARGINREQUIRED = 32;

		/// <summary>
		/// MODE_PLUSDI constant
		/// </summary>
		protected const int MODE_PLUSDI = 1;


		/// <summary>
		/// MODE_MINUSDI constant
		/// </summary>
		protected const int MODE_MINUSDI = 2;

		/// <summary>
		/// MODE_SIGNAL constant
		/// </summary>
		protected const int MODE_SIGNAL = 2;

		/// <summary>
		/// MODE_UPPER constant
		/// </summary>
		protected const int MODE_UPPER = 1;

		/// <summary>
		/// OBJ_RECTANGLE constant
		/// </summary>
		protected const int OBJ_RECTANGLE = 16;

		/// <summary>
		/// REASON_CHARTCHANGE constant
		/// </summary>
		protected const int REASON_CHARTCHANGE = 3;




		/// <summary>
		/// Draw line constant
		/// </summary>
		protected const int DRAW_LINE = 0;

		/// <summary>
		/// Empty value constant
		/// </summary>
		protected const int EMPTY_VALUE = int.MaxValue;

		#endregion

		#region Constants for files

		/// <summary>
		/// File write constant
		/// </summary>
		protected const int FILE_READ = 1;

		/// <summary>
		/// File write constant
		/// </summary>
		protected const int FILE_WRITE = 2;

		/// <summary>
		/// File write constant
		/// </summary>
		protected const int FILE_BIN = 4;

		/// <summary>
		/// File write constant
		/// </summary>
		protected const int FILE_CSV = 8;

		/// <summary>
		/// SEEK_END constant
		/// </summary>
		protected int SEEK_END = 2;

		/// <summary>
		/// OBJ_TREND constant
		/// </summary>
		protected int OBJ_TREND = 2;

		#endregion

		#region Others

		/// <summary>
		/// Returns TRUE if a thread for trading is occupied by another expert advisor, otherwise returns FALSE.
		/// See also IsTradeAllowed(). 
		/// </summary>
		/// <returns></returns>
		protected bool IsTradeContextBusy()
		{
			if (null == m_currentSnapshot)
			{
				return true;
			}
			bool result = !m_currentSnapshot.IsTradeLoggedOn;
			return result;
		}

		/// <summary>
		/// Returns the code of the uninitialization reason for the experts, custom indicators, and scripts. The returned values can be ones of Uninitialize reason codes. This function can also be called in function init() to analyze the reasons for deinitialization of the previour launch. 
		/// </summary>
		/// <returns></returns>
		protected int UninitializeReason()
		{
			throw new NotImplementedException();
		}

		#endregion

		#endregion

		#region construction

		/// <summary>
		/// 
		/// </summary>
		protected MqlAdapter()
		{
			this.Open = new BarPrices(BarPriceType.Open, this);
			this.Close = new BarPrices(BarPriceType.Close, this);
			this.Low = new BarPrices(BarPriceType.Low, this);
			this.High = new BarPrices(BarPriceType.High, this);
			this.Volume = new BarVolumes(this);

			Type type = this.GetType();
			m_init = type.GetMethod("init", BindingFlags.NonPublic | BindingFlags.Instance);
			m_start = type.GetMethod("start", BindingFlags.NonPublic | BindingFlags.Instance);
			m_deinit = type.GetMethod("deinit", BindingFlags.NonPublic | BindingFlags.Instance);
		}

		#endregion

		#region control methods

		internal void Initialize(Manager manager, string symbol, PriceType priceType, BarPeriod periodicity)
		{
			m_manager = manager;
			m_symbol = symbol;
			m_priceType = priceType;
			m_periodicity = periodicity;
			manager.Updated += OnUpdated;
		}

		internal void Start()
		{
			m_isStopped = false;
			m_thread = new Thread(ThreadLoop);
			m_thread.Start();
		}

		internal void Stop()
		{
			m_isStopped = true;
			m_event.Set();
			if (null != m_thread)
			{
				m_thread.Join();
				m_thread = null;
			}
		}

		#endregion

		#region internal properties

		internal Snapshot CurrentSnapshot
		{
			get { return m_currentSnapshot; }
		}

		#endregion

		#region thread methods

		private void ThreadLoop()
		{
			for (m_event.WaitOne(); !IsStopped(); m_event.WaitOne())
			{
				if (SafeThreadInit())
				{
					break;
				}
			}
			if (!IsStopped())
			{
				for (m_event.WaitOne(); !IsStopped(); m_event.WaitOne())
				{
					ThreadStep();
				}
			}
			ThreadDeinit();
		}

		private bool SafeThreadInit()
		{
			try
			{
				lock (m_synchronizer)
				{
					if (null == m_nextSnapshot)
					{
						return false;
					}
					m_currentSnapshot = m_nextSnapshot;
					m_nextSnapshot = null;
				}
				bool result = SafeIsSnapshotInitialized();
				if (result)
				{
					ThreadInit();
				}
				return result;
			}
			catch (System.Exception)
			{
				return false;
			}
		}

		private void ThreadInit()
		{
			if (!SafeIsSnapshotInitialized())
			{
				return;
			}
			if (null != m_init)
			{
				m_init.Invoke(this, null);
			}
		}

		private void ThreadStep()
		{
			lock (m_synchronizer)
			{
				if (null == m_nextSnapshot)
				{
					return;
				}
				m_currentSnapshot = m_nextSnapshot;
				m_nextSnapshot = null;
			}
			if (!SafeIsSnapshotInitialized())
			{
				return;
			}
			if (null != m_start)
			{
				m_start.Invoke(this, null);
			}
		}

		private void ThreadDeinit()
		{
			if (null != m_deinit)
			{
				m_deinit.Invoke(this, null);
			}
		}

		private bool SafeIsSnapshotInitialized()
		{
			try
			{
				return IsSnapshotInitialized();
			}
			catch (System.Exception)
			{
				return false;
			}
		}

		private bool IsSnapshotInitialized()
		{
			if (null == m_currentSnapshot)
			{
				return false;
			}
			if (null == m_currentSnapshot.AccountInfo)
			{
				return false;
			}
			if (null == m_currentSnapshot.Quotes)
			{
				return false;
			}
			if (null == m_currentSnapshot.TradeRecords)
			{
				return false;
			}
			if (null == m_currentSnapshot.Symbols)
			{
				return false;
			}
			if (!m_currentSnapshot.Quotes.ContainsKey(m_symbol))
			{
				return false;
			}
			if (null == m_currentSnapshot.Bars)
			{
				return false;
			}
			return true;
		}

		private void OnUpdated(object sender, EventArgs e)
		{
			lock (m_synchronizer)
			{
				m_nextSnapshot = m_manager.TakeSnapshot(m_symbol, m_priceType, m_periodicity);
			}
			m_event.Set();
		}

		#endregion

		#region orders methods

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		protected int HistoryTotal()
		{
			return 0;
		}

		/// <summary>
		/// Returns market and pending orders count.
		/// </summary>
		/// <returns></returns>
		protected int OrdersTotal()
		{
			int result = m_currentSnapshot.TradeRecords.Count;
			return result;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="index"></param>
		/// <param name="select"></param>
		/// <param name="pool"></param>
		/// <returns></returns>
		protected bool OrderSelect(int index, int select, int pool = MODE_TRADES)
		{
			if (MODE_HISTORY == pool)
			{
				throw new NotImplementedException(
					"Currently OrderSelect function is not implemented for MODE_HISTORY pool");
			}
			if (MODE_TRADES != pool)
			{
				string message = string.Format("Invalid pool = {0}", pool);
				throw new ArgumentOutOfRangeException("pool", pool, "Expected values: MODE_TRADES and MODE_HISTORY");
			}
			if ((SELECT_BY_POS != select) && (SELECT_BY_TICKET != select))
			{
				throw new ArgumentOutOfRangeException("select", select,
				                                      "Expected values: SELECT_BY_POS and SELECT_BY_TICKET");
			}
			Snapshot snapshot = m_currentSnapshot;
			if (null == snapshot)
			{
				m_selectedTradeRecord = null;
				return false;
			}
			List<TradeRecord> records = snapshot.TradeRecords;
			if (null == records)
			{
				m_selectedTradeRecord = null;
				return false;
			}
			if (SELECT_BY_POS == select)
			{
				if ((index < 0) || (index >= records.Count))
				{
					m_selectedTradeRecord = null;
					return false;
				}
				m_selectedTradeRecord = records[index];
				return true;
			}
			string orderId = index.ToString(CultureInfo.InvariantCulture);
			foreach (var element in records)
			{
				if (orderId == element.OrderId)
				{
					m_selectedTradeRecord = element;
					return true;
				}
			}
			m_selectedTradeRecord = null;
			return false;
		}

		#endregion

		#region positions methods

		/// <summary>
		/// Gets total buy amount for a symbol.
		/// </summary>
		/// <param name="symbol"></param>
		/// <returns></returns>
		protected double PositionBuyAmount(string symbol)
		{
			Position position = null;
			m_currentSnapshot.Positions.TryGetValue(symbol, out position);
			if (null == position)
			{
				return 0;
			}
			return position.BuyAmount;
		}

		/// <summary>
		/// Gets total sell amount for a symbol.
		/// </summary>
		/// <param name="symbol"></param>
		/// <returns></returns>
		protected double PositionSellAmount(string symbol)
		{
			Position position = null;
			m_currentSnapshot.Positions.TryGetValue(symbol, out position);
			if (null == position)
			{
				return 0;
			}
			return position.SellAmount;
		}

		#endregion

		#region date and time methods

		/// <summary>
		/// TIME_DATE gets result as "yyyy.mm.dd",
		/// </summary>
		protected const int TIME_DATE = 0x1;

		/// <summary>
		/// TIME_MINUTES gets result as "hh:mi",
		/// </summary>
		protected const int TIME_MINUTES = 0x2;

		/// <summary>
		/// TIME_SECONDS gets result as "hh:mi:ss".
		/// </summary>
		protected const int TIME_SECONDS = 0x4;

		/// <summary>
		/// Returns the current day of the month, i.e., the day of month of the last known server time.
		/// </summary>
		/// <returns></returns>
		protected int Day()
		{
			return m_currentSnapshot.ServerDateTime.Day;
		}

		/// <summary>
		/// Returns the current zero-based day of the week (0-Sunday,1,2,3,4,5,6) of the last known server time.
		/// </summary>
		/// <returns></returns>
		protected int DayOfWeek()
		{
			return (int) m_currentSnapshot.ServerDateTime.DayOfWeek;
		}

		/// <summary>
		/// Returns the current day of the year (1 means 1 January,..,365(6) does 31 December), i.e., the day of year of the last known server time.
		/// </summary>
		/// <returns></returns>
		protected int DayOfYear()
		{
			return m_currentSnapshot.ServerDateTime.DayOfYear;
		}

		/// <summary>
		/// Returns the current month as number (1-January,2,3,4,5,6,7,8,9,10,11,12), i.e., the number of month of the last known server time.
		/// </summary>
		/// <returns></returns>
		protected int Month()
		{
			return m_currentSnapshot.ServerDateTime.Month;
		}

		/// <summary>
		/// Returns the hour (0,1,2,..23) of the last known server time by the moment of the program start (this value will not change within the time of the program execution).
		/// Note: At the testing, the last known server time is modelled. 
		/// </summary>
		/// <returns></returns>
		protected int Hour()
		{
			return m_currentSnapshot.ServerDateTime.Hour;
		}

		/// <summary>
		/// Returns the current minute (0,1,2,..59) of the last known server time by the moment of the program start (this value will not change within the time of the program execution). 
		/// </summary>
		/// <returns></returns>
		protected int Minute()
		{
			return m_currentSnapshot.ServerDateTime.Minute;
		}

		/// <summary>
		/// Returns the amount of seconds elapsed from the beginning of the current minute of the last known server time by the moment of the program start (this value will not change within the time of the program execution). 
		/// </summary>
		/// <returns></returns>
		protected int Seconds()
		{
			return m_currentSnapshot.ServerDateTime.Second;
		}

		/// <summary>
		/// Returns the last known server time (time of incoming of the latest quote) as number of seconds elapsed from 00:00 January 1, 1970.
		/// </summary>
		/// <returns></returns>
		protected datetime TimeCurrent()
		{
			DateTime serverTime = m_currentSnapshot.ServerDateTime;
			datetime result = new datetime(serverTime);
			return result;
		}

		/// <summary>
		/// Returns day of month (1 - 31) for the specified date.
		/// </summary>
		/// <param name="date">datetime as number of seconds elapsed since midnight (00:00:00), January 1, 1970</param>
		/// <returns></returns>
		protected int TimeDay(datetime date)
		{
			return date.DateTime.Day;
		}

		/// <summary>
		/// Returns the zero-based day of week (0 means Sunday,1,2,3,4,5,6) for the specified date.
		/// </summary>
		/// <param name="date">datetime as number of seconds elapsed since midnight (00:00:00), January 1, 1970.</param>
		/// <returns></returns>
		protected int TimeDayOfWeek(datetime date)
		{
			return (int) date.DateTime.DayOfWeek;
		}

		/// <summary>
		/// Returns day (1 means 1 January,..,365(6) does 31 December) of year for the specified date.
		/// </summary>
		/// <param name="date">datetime as number of seconds elapsed since midnight (00:00:00), January 1, 1970</param>
		/// <returns></returns>
		protected int TimeDayOfYear(datetime date)
		{
			return date.DateTime.DayOfYear;
		}

		/// <summary>
		/// Returns the hour for the specified time.
		/// </summary>
		/// <param name="time">datetime as number of seconds elapsed since midnight (00:00:00), January 1, 1970</param>
		/// <returns></returns>
		protected int TimeHour(datetime time)
		{
			return time.DateTime.Hour;
		}

		/// <summary>
		/// Returns local computer time as number of seconds elapsed from 00:00 January 1, 1970.
		/// </summary>
		/// <returns></returns>
		protected datetime TimeLocal()
		{
			datetime result = new datetime(DateTime.Now);
			return result;
		}

		/// <summary>
		/// Returns the minute for the specified time. 
		/// </summary>
		/// <param name="time">datetime as number of seconds elapsed since midnight (00:00:00), January 1, 1970</param>
		/// <returns></returns>
		protected int TimeMinute(datetime time)
		{
			return time.DateTime.Minute;
		}

		/// <summary>
		/// Returns the month number for the specified time.
		/// </summary>
		/// <param name="time"></param>
		/// <returns></returns>
		protected int TimeMonth(datetime time)
		{
			return time.DateTime.Month;
		}

		/// <summary>
		/// Returns the amount of seconds elapsed from the beginning of the minute for the specified time.
		/// </summary>
		/// <param name="time">datetime as number of seconds elapsed since midnight (00:00:00), January 1, 1970</param>
		/// <returns></returns>
		protected int TimeSeconds(datetime time)
		{
			return time.DateTime.Second;
		}

		/// <summary>
		/// Returns year for the specified date.
		/// </summary>
		/// <param name="time">datetime as number of seconds elapsed since midnight (00:00:00), January 1, 1970</param>
		/// <returns></returns>
		protected int TimeYear(datetime time)
		{
			return time.DateTime.Year;
		}

		/// <summary>
		/// Converts value containing time in seconds that has passed since January 1, 1970, into a string of "yyyy.mm.dd hh:mi" format. 
		/// </summary>
		/// <param name="value"></param>
		/// <param name="mode"></param>
		/// <returns></returns>
		protected string TimeToStr(datetime value, int mode = TIME_DATE | TIME_MINUTES)
		{
			string result = string.Empty;
			DateTime t = value.DateTime;
			if (0 != (mode & TIME_DATE))
			{
				result = t.ToString("yyyy.MM.dd ");
			}
			if (0 != (mode & TIME_SECONDS))
			{
				result += t.ToString("hh:mm:ss");
			}
			else if (0 != (mode & TIME_MINUTES))
			{
				result += t.ToString("hh:mm");
			}
			return result;
		}

		/// <summary>
		/// Converts string in the format "yyyy.mm.dd hh:mi" to datetime type (the amount of seconds that have passed since 1 Jan., 1970). 
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		protected datetime StrToTime(string value)
		{
			throw new NotImplementedException("TimeToStr not implemented");
		}

		/// <summary>
		/// Returns the current year, i.e., the year of the last known server time.
		/// </summary>
		/// <returns></returns>
		protected int Year()
		{
			return m_currentSnapshot.ServerDateTime.Year;
		}

		#endregion

		#region advisers and current symbol settings

		/// <summary>
		/// Returns a text string with the name of the current financial instrument.
		/// </summary>
		/// <returns>a current financial instrument</returns>
		protected string Symbol()
		{
			return m_symbol;
		}

		#endregion

		#region selected order methods

		/// <summary>
		/// Returns type of the selected order by OrderSelect method.
		/// </summary>
		/// <returns>type of the selected order</returns>
		/// <exception cref="System.ArgumentNullException">if order has not been selected</exception>
		protected int OrderType()
		{
			TradeRecord record = GetSelectedTradeRecord();
			if (TradeRecordSide.Buy == record.Side)
			{
				if (TradeRecordType.Position == record.Type)
				{
					return OP_BUY;
				}
				else if (TradeRecordType.Limit == record.Type)
				{
					return OP_BUYLIMIT;
				}
				else
				{
					return OP_BUYSTOP;
				}
			}
			else
			{
				if (TradeRecordType.Position == record.Type)
				{
					return OP_SELL;
				}
				else if (TradeRecordType.Limit == record.Type)
				{
					return OP_SELLLIMIT;
				}
				else
				{
					return OP_SELLSTOP;
				}
			}
		}

		/// <summary>
		/// Returns the net profit value (without swaps or commissions) for the selected order.
		/// </summary>
		/// <returns>profit value</returns>
		protected double OrderProfit()
		{
			TradeRecord record = GetSelectedTradeRecord();
			double result = record.Profit.Value;
			return result;
		}

		/// <summary>
		/// Returns symbol of the selected order by OrderSelect method.
		/// </summary>
		/// <returns>symbol of the selected order</returns>
		/// <exception cref="System.ArgumentNullException">if order has not been selected</exception>
		protected string OrderSymbol()
		{
			TradeRecord record = GetSelectedTradeRecord();
			return record.Symbol;
		}

		/// <summary>
		/// Returns ticket number for the selected order.
		/// </summary>
		/// <returns>ticket number of the selected order</returns>
		/// <exception cref="System.ArgumentNullException">if order has not been selected</exception>
		protected int OrderTicket()
		{
			TradeRecord record = GetSelectedTradeRecord();
			int result = int.Parse(record.OrderId, CultureInfo.InvariantCulture);
			return result;
		}

		/// <summary>
		/// Returns amount of lots for the selected order.
		/// </summary>
		/// <returns>volume of the selected order in lots</returns>
		protected double OrderLots()
		{
			TradeRecord record = GetSelectedTradeRecord();
			SymbolInfo info = m_currentSnapshot.Symbols[record.Symbol];
			double result = record.Volume/info.RoundLot;
			return result;
		}

		/// <summary>
		/// Returns the number of closed orders in the account history loaded into the terminal. The history list size depends on the current settings of the "Account history" tab of the terminal. 
		/// </summary>
		/// <returns></returns>
		protected int OrdersHistoryTotal()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns close price for the currently selected order.
		/// Note: The order must be previously selected by the OrderSelect() function. 
		/// </summary>
		/// <returns></returns>
		protected double OrderClosePrice()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns stop loss value for the currently selected order.
		/// </summary>
		/// <returns>stop loss value or zero</returns>
		protected double OrderStopLoss()
		{
			TradeRecord record = GetSelectedTradeRecord();
			SymbolInfo info = m_currentSnapshot.Symbols[record.Symbol];
			double result = record.StopLoss ?? 0;
			return result;
		}

		/// <summary>
		/// Returns take profit value for the currently selected order.
		/// </summary>
		/// <returns>take profit value or zero</returns>
		protected double OrderTakeProfit()
		{
			TradeRecord record = GetSelectedTradeRecord();
			SymbolInfo info = m_currentSnapshot.Symbols[record.Symbol];
			double result = record.TakeProfit ?? 0;
			return result;
		}

		/// <summary>
		/// Returns open price for the currently selected order.
		/// </summary>
		/// <returns>open price value</returns>
		protected double OrderOpenPrice()
		{
			TradeRecord record = GetSelectedTradeRecord();
			return record.Price;
		}

		/// <summary>
		/// Returns open time for the currently selected order.
		/// </summary>
		/// <returns>open time value</returns>
		protected datetime OrderOpenTime()
		{
			TradeRecord record = GetSelectedTradeRecord();
			DateTime value = record.Created ?? datetime.ReferenceTime;
			datetime result = new datetime(value);
			return result;
		}

		/// <summary>
		/// Currently magic numbers are not supported by server.
		/// </summary>
		/// <returns>always zero</returns>
		protected int OrderMagicNumber()
		{
			return 0;
		}

		/// <summary>
		/// Returns swap value for the currently selected order.
		/// </summary>
		/// <returns></returns>
		protected double OrderSwap()
		{
			TradeRecord record = GetSelectedTradeRecord();
			return record.Swap;
		}

		/// <summary>
		/// Returns calculated commission for the currently selected order.
		/// </summary>
		/// <returns></returns>
		protected double OrderCommission()
		{
			TradeRecord record = GetSelectedTradeRecord();
			return record.Commission;
		}

		/// <summary>
		/// Returns comment for the selected order.\
		/// Note: The order must be previously selected by the OrderSelect() function
		/// </summary>
		/// <returns></returns>
		protected string OrderComment()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns expiration date for the selected pending order.
		/// </summary>
		/// <returns></returns>
		protected datetime OrderExpiration()
		{
			TradeRecord record = GetSelectedTradeRecord();
			return record.Expiration ?? new datetime();
		}

		private TradeRecord GetSelectedTradeRecord()
		{
			TradeRecord result = m_selectedTradeRecord;
			if (null == result)
			{
				throw new ArgumentNullException("Use OrderSelect method to select order");
			}
			return result;
		}

		#endregion

		#region quotes

		/// <summary>
		/// Refreshing of data in pre-defined variables and series arrays.
		/// </summary>
		/// <returns></returns>
		protected bool RefreshRates()
		{
			lock (m_synchronizer)
			{
				if (null != m_nextSnapshot)
				{
					m_currentSnapshot = m_nextSnapshot;
				}
			}
			return true;
		}

		/// <summary>
		///  Returns various market data.
		/// </summary>
		/// <param name="symbol">Security symbol</param>
		/// <param name="type">
		/// Expected: MODE_BID, MODE_ASK, MODE_POINT, MODE_DIGITS, MODE_SPREAD, MODE_MINLOT, MODE_LOTSTEP, MODE_MAXLOT
		/// </param>
		/// <returns></returns>
		protected double MarketInfo(string symbol, int type)
		{
			if (MODE_BID == type)
			{
				Quote quote = QuoteFromSymbol(symbol);
				return quote.Bid;
			}
			if (MODE_ASK == type)
			{
				Quote quote = QuoteFromSymbol(symbol);
				return quote.Ask;
			}
			if (MODE_SPREAD == type)
			{
				Quote quote = QuoteFromSymbol(symbol);
				return quote.Spread;
			}
			SymbolInfo info = m_currentSnapshot.Symbols[symbol];
			if (MODE_DIGITS == type)
			{
				return info.Precision;
			}
			if (MODE_POINT == type)
			{
				int digits = info.Precision;
				double result = Math.Pow(10, -digits);
				return result;
			}
			if (MODE_MINLOT == type)
			{
				return (info.MinTradeVolume/info.RoundLot);
			}
			if (MODE_LOTSTEP == type)
			{
				return (info.TradeVolumeStep/info.RoundLot);
			}
			if (MODE_MAXLOT == type)
			{
				return (info.MaxTradeVolume/info.RoundLot);
			}
			if (MODE_LOTSIZE == type)
			{
				return info.RoundLot;
			}
			if (MODE_SWAPLONG == type)
			{
				Debug.Fail("if (MODE_SWAPLONG == type)");
				return 0;
			}
			if (MODE_SWAPSHORT == type)
			{
				Debug.Fail("if (MODE_SWAPSHORT == type)");
				return 0;
			}
			string message =
				string.Format(
					"Unsupported type = {0}; expected = MODE_BID, MODE_ASK, MODE_POINT, MODE_DIGITS, MODE_SPREAD, MODE_MINLOT, MODE_LOTSTEP or MODE_MAXLOT",
					type);
			throw new ArgumentException(message);
		}

		/// <summary>
		/// The latest known buyer's price (bid price) of the current symbol.
		/// </summary>
		protected double Bid
		{
			get
			{
				Quote quote = QuoteFromSymbol(m_symbol);
				double result = 0;
				if (null != quote)
				{
					result = quote.Bid;
				}
				return result;
			}
		}

		/// <summary>
		/// The latest known seller's price (ask price) for the current symbol.
		/// </summary>
		protected double Ask
		{
			get
			{
				Quote quote = QuoteFromSymbol(m_symbol);
				double result = 0;
				if (null != quote)
				{
					result = quote.Ask;
				}
				return result;
			}
		}

		/// <summary>
		/// The current symbol point value in the quote currency.
		/// </summary>
		protected double Point
		{
			get
			{
				int digits = this.Digits;
				double result = Math.Pow(10, -digits);
				return result;
			}
		}

		/// <summary>
		/// Number of digits after decimal point for the current symbol prices.
		/// </summary>
		protected int Digits
		{
			get
			{
				SymbolInfo info = m_currentSnapshot.Symbols[m_symbol];
				return info.Precision;
			}
		}

		private Quote QuoteFromSymbol(string symbol)
		{
			Snapshot snapshot = m_currentSnapshot;
			if (null == snapshot)
			{
				return null;
			}
			Quote result = null;
			snapshot.Quotes.TryGetValue(symbol, out result);
			return result;
		}

		#endregion

		#region bars history

		/// <summary>
		/// Series array that contains open prices of each bar of the current chart.
		/// </summary>
		protected BarPrices Open { get; private set; }

		/// <summary>
		/// Series array that contains close prices for each bar of the current chart.
		/// </summary>
		protected BarPrices Close { get; private set; }

		/// <summary>
		/// Series array that contains the highest prices of each bar of the current chart.
		/// </summary>
		protected BarPrices High { get; private set; }

		/// <summary>
		/// Series array that contains the lowest prices of each bar of the current chart.
		/// </summary>
		protected BarPrices Low { get; private set; }

		/// <summary>
		/// Series array that contains tick volumes of each bar of the current chart.
		/// </summary>
		protected BarVolumes Volume { get; private set; }

		/// <summary>
		/// Series array that contains open time of each bar of the current chart. Data like datetime represent time, in seconds, that has passed since 00:00 a.m. of 1 January, 1970.
		/// Series array elements are indexed in the reverse order, i.e., from the last one to the first one. The current bar which is the last in the array is indexed as 0. The oldest bar, the first in the chart, is indexed as Bars-1.
		/// </summary>
		protected datetime[] Time { get; set; }

		/// <summary>
		/// Number of bars in the current chart.
		/// </summary>
		protected int Bars
		{
			get { return m_currentSnapshot.Bars.Length; }
		}

		/// <summary>
		/// Calculates the Bollinger Bands® indicator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="deviation"></param>
		/// <param name="bands_shift"></param>
		/// <param name="applied_price"></param>
		/// <param name="mode"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iBands(string symbol, int timeframe, int period, int deviation, int bands_shift, int applied_price,
		                        int mode, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns the number of bars on the specified chart.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicator; NULL means the current symbol</param>
		/// <param name="timeframe">timeframe; tt can be any of Timeframe enumeration values; 0 means the current chart timeframe</param>
		/// <returns></returns>
		protected int iBars(string symbol, int timeframe)
		{
			Bar[] bars = GetBars(symbol, timeframe);
			return bars.Length;
		}

		/// <summary>
		/// Search for bar by open time. The function returns bar shift with the open time specified.
		/// If the bar having the specified open time is missing, the function will return -1 or the nearest bar shift depending on the exact.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicator; NULL means the current symbol</param>
		/// <param name="timeframe">tt can be any of Timeframe enumeration values; 0 means the current chart timeframe</param>
		/// <param name="time">value to find (bar's open time)</param>
		/// <param name="exact">return mode when bar not found; false - iBarShift returns nearest; true - iBarShift returns -1. </param>
		/// <returns></returns>
		protected int iBarShift(string symbol, int timeframe, datetime time, bool exact = false)
		{
			int shift = -1;
			int result = -1;
			int minimumDelta = int.MaxValue;
			Bar[] bars = GetBars(symbol, timeframe);
			foreach (var element in bars)
			{
				++shift;
				datetime current = element.From;
				int delta = Math.Abs(current.Value - time.Value);
				if (delta < minimumDelta)
				{
					delta = minimumDelta;
					result = shift;
				}
			}
			if (-1 == result)
			{
				return result;
			}
			if (0 == minimumDelta)
			{
				return result;
			}
			if (exact)
			{
				result = -1;
			}
			return result;
		}

		/// <summary>
		/// Calculates the Bears Power indicator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="applied_price"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iBearsPower(string symbol, int timeframe, int period, int applied_price, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Bulls Power indicator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="applied_price"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iBullsPower(string symbol, int timeframe, int period, int applied_price, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Commodity channel index and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="applied_price"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iCCI(string symbol, int timeframe, int period, int applied_price, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the specified custom indicator and returns its value. The custom indicator must be compiled (*.EX4 file) and be in the terminal_directory\experts\indicators directory. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="name"></param>
		/// <param name="dataPoint"></param>
		/// <param name="mode"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iCustom(string symbol, int timeframe, string name, object dataPoint, int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift, dataPoint);
		}


		protected double iCustom(string symbol, int timeframe, string name, int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift);
		}


		protected double iCustom(string symbol, int timeframe, string name,
		                         object dataPoint, object dataPoint2,
		                         int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift);
		}

		protected double iCustom(string symbol, int timeframe, string name,
		                         object dataPoint, object dataPoint2, object dataPoint3,
		                         int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift);
		}

		protected double iCustom(string symbol, int timeframe, string name,
		                         object dataPoint, object dataPoint2, object dataPoint3, object dataPoint4,
		                         int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift);
		}

		protected double iCustom(string symbol, int timeframe, string name,
		                         object dataPoint, object dataPoint2, object dataPoint3, object dataPoint4, object dataPoint5,
		                         int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift);
		}

		protected double iCustom(string symbol, int timeframe, string name,
		                         object dataPoint, object dataPoint2, object dataPoint3, object dataPoint4, object dataPoint5,
		                         object dataPoint6,
		                         int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift);
		}

		protected double iCustom(string symbol, int timeframe, string name,
		                         object dataPoint, object dataPoint2, object dataPoint3, object dataPoint4, object dataPoint5,
		                         object dataPoint6, object dataPoint7,
		                         int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift);
		}

		protected double iCustom(string symbol, int timeframe, string name,
		                         object dataPoint, object dataPoint2, object dataPoint3, object dataPoint4, object dataPoint5,
		                         object dataPoint6, object dataPoint7, object dataPoint8, object dataPoint9,
		                         int mode, int shift)
		{
			return iCustomImpl(symbol, timeframe, name, mode, shift);
		}

		protected double iCustomImpl(string symbol, int timeframe, string name, int mode, int shift,
		                             params object[] dataPoints)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns Close value for the bar of indicated symbol with timeframe and shift. If local history is empty (not loaded), function returns 0.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicator; NULL means the current symbol</param>
		/// <param name="timeframe">it can be any of Timeframe enumeration values; 0 means the current chart timeframe</param>
		/// <param name="shift">index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago)</param>
		/// <returns></returns>
		protected double iClose(string symbol, int timeframe, int shift)
		{
			Bar[] bars = GetBars(symbol, timeframe);
			Bar bar = bars[shift];
			return bar.Close;
		}

		/// <summary>
		/// Calculates the DeMarker indicator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="period"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iDeMarker(string symbol, int timeframe, int period, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Calculates the Envelopes indicator and returns its value. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="timeframe"></param>
		/// <param name="ma_period"></param>
		/// <param name="ma_method"></param>
		/// <param name="ma_shift"></param>
		/// <param name="applied_price"></param>
		/// <param name="deviation"></param>
		/// <param name="mode"></param>
		/// <param name="shift"></param>
		/// <returns></returns>
		protected double iEnvelopes(string symbol, int timeframe, int ma_period, int ma_method, int ma_shift,
		                            int applied_price, double deviation, int mode, int shift)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns High value for the bar of indicated symbol with timeframe and shift. If local history is empty (not loaded), function returns 0.
		/// </summary>
		/// <param name="symbol">symbol on that data need to calculate indicator; NULL means current symbol</param>
		/// <param name="timeframe">it can be any of Timeframe enumeration values; 0 means the current chart timeframe</param>
		/// <param name="shift">index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago)</param>
		/// <returns></returns>
		protected double iHigh(string symbol, int timeframe, int shift)
		{
			Bar[] bars = GetBars(symbol, timeframe);
			Bar bar = bars[shift];
			return bar.High;
		}

		/// <summary>
		/// Returns the shift of the maximum value over a specific number of periods depending on type.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicatorl null means the current symbol</param>
		/// <param name="timeframe">timeframe; it can be any of Timeframe enumeration values; 0 means the current chart timeframe</param>
		/// <param name="type"> MODE_OPEN, MODE_LOW, MODE_HIGH, MODE_CLOSE, MODE_VOLUME, MODE_TIME</param>
		/// <param name="count">number of periods (in direction from the start bar to the back one) on which the calculation is carried out</param>
		/// <param name="start">shift showing the bar, relative to the current bar, that the data should be taken from</param>
		/// <returns></returns>
		protected int iHighest(string symbol, int timeframe, int type, int count = WHOLE_ARRAY, int start = 0)
		{
			BarValues values = GetBarValues(symbol, timeframe, type);
			int end = Math.Min(values.Count, start + count);
			if (WHOLE_ARRAY == count)
			{
				end = values.Count;
			}
			int result = -1;
			double maximum = -double.MaxValue;

			for (int index = start; result < end; ++index)
			{
				double value = values[index];
				if (value > maximum)
				{
					maximum = value;
					result = index;
				}
			}
			return result;
		}

		/// <summary>
		/// Returns Low value for the bar of indicated symbol with timeframe and shift. If local history is empty (not loaded), function returns 0.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicator; NULL means the current symbol</param>
		/// <param name="timeframe">it can be any of Timeframe enumeration values. 0 means the current chart timeframe</param>
		/// <param name="shift">index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago)</param>
		/// <returns></returns>
		protected double iLow(string symbol, int timeframe, int shift)
		{
			Bar[] bars = GetBars(symbol, timeframe);
			Bar bar = bars[shift];
			return bar.Low;
		}

		/// <summary>
		/// Returns the shift of the least value over a specific number of periods depending on type.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicator; NULL means the current symbol</param>
		/// <param name="timeframe">it can be any of Timeframe enumeration values; 0 means the current chart timeframe</param>
		/// <param name="type">series array identifier; it can be any of Series array identifier enumeration values</param>
		/// <param name="count">number of periods (in direction from the start bar to the back one) on which the calculation is carried out</param>
		/// <param name="start">shift showing the bar, relative to the current bar, that the data should be taken from</param>
		/// <returns></returns>
		protected int iLowest(string symbol, int timeframe, int type, int count = WHOLE_ARRAY, int start = 0)
		{
			BarValues values = GetBarValues(symbol, timeframe, type);
			int end = Math.Min(values.Count, start + count);
			if (WHOLE_ARRAY == count)
			{
				end = values.Count;
			}
			int result = -1;
			double minimum = double.MaxValue;

			for (int index = start; result < end; ++index)
			{
				double value = values[index];
				if (value < minimum)
				{
					minimum = value;
					result = index;
				}
			}
			return result;
		}

		/// <summary>
		/// Returns Open value for the bar of indicated symbol with timeframe and shift. If local history is empty (not loaded), function returns 0.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicator; NULL means the current symbol</param>
		/// <param name="timeframe">it can be any of Timeframe enumeration values; 0 means the current chart timeframe</param>
		/// <param name="shift">index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago)</param>
		/// <returns></returns>
		protected double iOpen(string symbol, int timeframe, int shift)
		{
			Bar[] bars = GetBars(symbol, timeframe);
			Bar bar = bars[shift];
			return bar.Open;
		}

		/// <summary>
		/// Returns Time value for the bar of indicated symbol with timeframe and shift. If local history is empty (not loaded), function returns 0.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicator; NULL means the current symbol</param>
		/// <param name="timeframe">it can be any of Timeframe enumeration values; 0 means the current chart timeframe</param>
		/// <param name="shift">index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago)</param>
		/// <returns></returns>
		protected datetime iTime(string symbol, int timeframe, int shift)
		{
			Bar[] bars = GetBars(symbol, timeframe);
			return 0;
		}

		/// <summary>
		/// Returns Tick Volume value for the bar of indicated symbol with timeframe and shift. If local history is empty (not loaded), function returns 0.
		/// </summary>
		/// <param name="symbol">symbol the data of which should be used to calculate indicator; NULL means the current symbol</param>
		/// <param name="timeframe">it can be any of Timeframe enumeration values. 0 means the current chart timeframe</param>
		/// <param name="shift">index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago)</param>
		/// <returns></returns>
		protected int iVolume(string symbol, int timeframe, int shift)
		{
			Bar[] bars = GetBars(symbol, timeframe);
			Bar bar = bars[shift];
			return bar.Volume;
		}

		private Bar[] GetBars(string symbol, int timeframe)
		{
			if (null == symbol)
			{
				symbol = m_symbol;
			}
			BarPeriod periodicity = PeriodicityFromTimeFrame(timeframe);
			Bar[] result = m_currentSnapshot.GetBars(symbol, periodicity);
			return result;
		}

		private BarPeriod PeriodicityFromTimeFrame(int timeframe)
		{
			if (0 == timeframe)
			{
				return m_periodicity;
			}
			if (PERIOD_M1 == timeframe)
			{
				return BarPeriod.M1;
			}
			if (PERIOD_M5 == timeframe)
			{
				return BarPeriod.M5;
			}
			if (PERIOD_M15 == timeframe)
			{
				return BarPeriod.M15;
			}
			if (PERIOD_M30 == timeframe)
			{
				return BarPeriod.M30;
			}
			if (PERIOD_H1 == timeframe)
			{
				return BarPeriod.H1;
			}
			if (PERIOD_H4 == timeframe)
			{
				return BarPeriod.H4;
			}
			if (PERIOD_D1 == timeframe)
			{
				return BarPeriod.D1;
			}
			if (PERIOD_W1 == timeframe)
			{
				return BarPeriod.W1;
			}
			if (PERIOD_MN1 == timeframe)
			{
				return BarPeriod.MN1;
			}
			string message = string.Format("Unsupported time frame = {0}", timeframe);
			throw new ArgumentException(message, "timeframe");
		}

		#region Global variables

		/// <summary>
		/// Returns TRUE if the global variable exists, otherwise, returns FALSE. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		protected bool GlobalVariableCheck(string name)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Deletes the global variable. If the function succeeds, the returned value will be TRUE, otherwise, it will be FALSE. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		protected bool GlobalVariableDel(string name)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns the value of an existing global variable or 0 if an error occurs. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		protected double GlobalVariableGet(string name)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function returns the name of a global variable by its index in the list of global variables. To get the detailed error information, one has to call the GetLastError(). 
		/// </summary>
		/// <param name="index">Index in the list of global variables. It must exceed or be equal to 0 and be less than GlobalVariablesTotal().</param>
		/// <returns></returns>
		protected string GlobalVariableName(int index)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sets a new value of the global variable. If it does not exist, the system creates a new gloabl variable. If the function succeeds, the returned value will be the last access time. Otherwise, the returned value will be 0. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="name"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		protected datetime GlobalVariableSet(string name, double value)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sets the new value of the existing global variable if the current value equals to the third parameter check_value. If there is no global variable, the function will generate error ERR_GLOBAL_VARIABLE_NOT_FOUND (4058) and return FALSE. When successfully executed, the function returns TRUE, otherwise, it returns FALSE. To get the detailed error information, one has to call the GetLastError() function.
		/// If the current value of the global variable differs from the check_value, the function will return FALSE.
		/// The function provides atomic access to the global variable, this is why it can be used for providing of a semaphore at interaction of several experts working simultaneously within one client terminal. 
		/// </summary>
		/// <param name="name"></param>
		/// <param name="value"></param>
		/// <param name="check_value"></param>
		/// <returns></returns>
		protected bool GlobalVariableSetOnCondition(string name, double value, double check_value)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Deletes global variables. If the name prefix is not specified, all global variables will be deleted. Otherwise, only those variables will be deleted, the names of which begin with the specified prefix. The function returns the count of deleted variables. 
		/// </summary>
		/// <param name="prefix_name"></param>
		/// <returns></returns>
		protected int GlobalVariablesDeleteAll(string prefix_name = null)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function returns the total count of global variables. 
		/// </summary>
		/// <returns></returns>
		protected int GlobalVariablesTotal()
		{
			throw new NotImplementedException();
		}

		#endregion

		#region File methods

		/// <summary>
		/// Closes file previously opened by the FileOpen() function. 
		/// </summary>
		/// <param name="handle"></param>
		protected void FileClose(int handle)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Removes specified file name. To get the detailed error information, call GetLastError().
		/// Files can only be deleted if they are in the terminal_dir\experts\files directory (terminal_directory\tester\files, in case of testing) or its subdirectories. 
		/// </summary>
		/// <param name="filename"></param>
		protected void FileDelete(string filename)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Flushes all data stored in the file buffer to the disk.
		/// Notes: The FileFlush() function must be called between operations of file reading and writing in the file.
		/// At file closing, the data are flushed to the disk automatically, so there is no need to call the FileFlush() function before calling of the FileClose() function. 
		/// </summary>
		/// <param name="handle"></param>
		protected void FileFlush(int handle)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns logical true if file pointer is at the end of the file, otherwise returns false. To get the detailed error information, call GetLastError() function. If the file end is reached during reading, the GetLastError() function will return error ERR_END_OF_FILE (4099). 
		/// </summary>
		/// <param name="handle"></param>
		/// <returns></returns>
		protected bool FileIsEnding(int handle)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// For CSV file returns logical true if file pointer is at the end of the line, otherwise returns false. To get the detailed error information, call GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <returns></returns>
		protected bool FileIsLineEnding(int handle)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Opens file for input and/or output. Returns a file handle for the opened file or -1 (if the function fails). To get the detailed error information, call GetLastError() function.
		/// Notes: Files can only be opened in the terminal_directory\experts\files folder (terminal_directory\tester\files if for expert testing) or in its subfolders.
		/// FILE_BIN and FILE_CSV modes cannot be used simultaneously.
		/// If FILE_WRITE does not combine with FILE_READ, a zero-length file will be opened. If even the file containd some data, they will be deleted. If there is a need to add data to an existing file, it must be opened using combination of FILE_READ | FILE_WRITE.
		/// If FILE_READ does not combine with FILE_WRITE, the file will be opened only if it already exists. If the file does not exist, it can be created using the FILE_WRITE mode.
		/// No more than 32 files can be opened within an executable module simultaneously. Handles of files opened in the same module cannot be passed to other modules (libraries). 
		/// </summary>
		/// <param name="filename"></param>
		/// <param name="mode"></param>
		/// <param name="delimiter"></param>
		/// <returns></returns>
		protected int FileOpen(string filename, int mode, int delimiter = ';')
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Opens file in the current history directory (terminal_directory\history\server_name) or in its subfolders. Returns the file handle for the opened file. If the function fails, the returned value is -1. To get the detailed error information, call the GetLastError() function.
		/// Notes: Client terminal can connect to servers of different brokerage companies. History data (HST files) for each brokerage company are stored in the corresponding subfolder of the terminal_directory\history folder.
		/// The function can be useful to form own history data for a non-standard symbol and/or period. The file formed in the history folder can be opened offline, not data pumping is needed to chart it. 
		/// </summary>
		/// <param name="filename"></param>
		/// <param name="mode"></param>
		/// <param name="delimiter"></param>
		/// <returns></returns>
		protected int FileOpenHistory(string filename, int mode, int delimiter = ';')
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Reads the specified amount of elements from the binary file into array. Before reading, make sure that the array is large enough. Returns the amount of actually read elements.
		/// To get the detailed error information, call the GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="array"></param>
		/// <param name="start"></param>
		/// <param name="count"></param>
		/// <returns></returns>
		protected int FileReadArray(int handle, ref object[] array, int start, int count)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// sizeof(char)
		/// </summary>
		protected const int CHAR_VALUE = 1;

		/// <summary>
		/// sizeof(shart)
		/// </summary>
		protected const int SHORT_VALUE = 2;

		/// <summary>
		/// sizeof(int32)
		/// </summary>
		protected const int LONG_VALUE = 4;

		/// <summary>
		/// sizeof(double)
		/// </summary>
		protected const int DOUBLE_VALUE = 8;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="size"></param>
		/// <returns></returns>
		protected double FileReadDouble(int handle, int size = DOUBLE_VALUE)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="size"></param>
		/// <returns></returns>
		protected int FileReadInteger(int handle, int size = DOUBLE_VALUE)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Read the number from the current file position before the delimiter. Only for CSV files.
		/// To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <returns></returns>
		protected double FileReadNumber(int handle)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function reads the string from the current file position. Applies to both CSV and binary files. For text files, the string will be read before the delimiter. For binary file, the given count of characters will be read to the string. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="length"></param>
		/// <returns></returns>
		protected string FileReadString(int handle, int length = 0)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function moves the file pointer to a new position that is an offset, in bytes, from the beginning, the end or the current file position. The next reading or writing are made at a new position.
		/// If file pointer has been moved successfully, the function returns TRUE, otherwise, it returns FALSE. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="offset"></param>
		/// <param name="origin"></param>
		/// <returns></returns>
		protected bool FileSeek(int handle, int offset, int origin)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function returns file size in bytes. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <returns></returns>
		protected int FileSize(int handle)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="handle"></param>
		/// <returns></returns>
		protected int FileTell(int handle)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function writes a double value with floating point to a binary file. If the format is specified as FLOAT_VALUE, the value will be written as a 4-bytes floating point number (of the float type), otherwise, it will be written in the 8-bytes floating point format (of the double type).
		/// Returns the actually written bytes count or a negative value if an error occurs.
		/// To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="value"></param>
		/// <param name="size"></param>
		/// <returns></returns>
		protected int FileWriteDouble(int handle, double value, int size = DOUBLE_VALUE)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function writes the integer value to a binary file. If the size is SHORT_VALUE, the value will be written as a 2-byte integer (the short type), if the size is CHAR_VALUE, the value will be written as a 1-byte integer (the char type), and if the size is LONG_VALUE, the value will be written as a 4-byte integer (the long int type).
		/// Returns the actually written bytes count or a negative value if an error occurs.
		/// To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="value"></param>
		/// <param name="size"></param>
		/// <returns></returns>
		protected int FileWriteInteger(int handle, int value, int size = LONG_VALUE)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// The function writes the string to a binary file from the current file position.
		/// Returns the actually written bytes count or a negative value if an error occurs.
		/// To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="value"></param>
		/// <param name="length"></param>
		/// <returns></returns>
		private int FileWriteString(int handle, string value, int length)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="handle"></param>
		/// <param name="items"></param>
		/// <returns></returns>
		protected int FileWrite(int handle, params object[] items)
		{
			throw new NotImplementedException();
		}

		#endregion

		private BarValues GetBarValues(string symbol, int timeframe, int type)
		{
			Bar[] bars = GetBars(symbol, timeframe);

			BarValues result = null;

			if (MODE_OPEN == type)
			{
				result = new BarValues(bars, BarValues.Open);
			}
			else if (MODE_LOW == type)
			{
				result = new BarValues(bars, BarValues.Low);
			}
			else if (MODE_HIGH == type)
			{
				result = new BarValues(bars, BarValues.High);
			}
			else if (MODE_CLOSE == type)
			{
				result = new BarValues(bars, BarValues.Close);
			}
			else if (MODE_VOLUME == type)
			{
				result = new BarValues(bars, BarValues.Volume);
			}
			else if (MODE_TIME == type)
			{
				result = new BarValues(bars, BarValues.Time);
			}
			else
			{
				string message = string.Format("Unsupported type = {0}", type);
				throw new ArgumentException(message, "type");
			}
			return result;
		}

		#endregion

		#region trading methods

		/// <summary>
		/// 
		/// </summary>
		/// <param name="symbol">symbol for trading</param>
		/// <param name="cmd">operation type</param>
		/// <param name="volume">number of lots</param>
		/// <param name="price">preferred price of the trade; ignored for market requests</param>
		/// <param name="slippage">ignored</param>
		/// <param name="stoploss">stop loss level.</param>
		/// <param name="takeprofit">take profit level</param>
		/// <param name="comment">ignored</param>
		/// <param name="magic">ignored</param>
		/// <param name="expiration">order expiration time (for pending orders only)</param>
		/// <param name="color">ignored</param>
		/// <returns></returns>
		protected int OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss,
		                        double takeprofit, string comment = null, int magic = 0, int expiration = 0,
		                        int color = CLR_NONE)
		{
			try
			{
				TradeCommand command;
				TradeRecordSide side;
				ConvertCmdToCommandAndSide(cmd, out command, out side);
				SymbolInfo info = m_currentSnapshot.Symbols[symbol];
				double volumeInLots = volume*info.RoundLot;

				double? stopLossPrice = (stoploss > 0) ? (double?) stoploss : null;
				double? takeProfitPrice = (takeprofit > 0) ? (double?) takeprofit : null;
				TradeRecord record = m_manager.Trader.Server.SendOrder(symbol, command, side, price, volumeInLots, stopLossPrice,
				                                                       takeProfitPrice, null, null);

				SafeRefreshSnapshot();

				int result = int.Parse(record.OrderId, CultureInfo.InvariantCulture);
				return result;
			}
			catch (System.Exception)
			{
				return 0;
			}
		}

		/// <summary>
		/// Deletes previously opened pending order.
		/// </summary>
		/// <param name="ticket">unique number of the order ticket</param>
		/// <param name="Color"></param>
		/// <returns>true, if the corresponded order has been delete, otherwise false</returns>
		protected bool OrderDelete(int ticket, int Color = CLR_NONE)
		{
			try
			{
				TradeRecord record = TradeRecordFromTicket(ticket);
				if (null == record)
				{
					return false;
				}
				record.Delete();

				SafeRefreshSnapshot();

				return true;
			}
			catch (System.Exception)
			{
				return false;
			}
		}

		/// <summary>
		/// Count all objects with any types
		/// </summary>
		protected const int EMPTY = -1;

		/// <summary>
		/// Changes the object description. For objects of OBJ_TEXT and OBJ_LABEL, this description is shown as a text line in the chart. If the function succeeds, the returned value will be TRUE. Otherwise, it is FALSE. To get the detailed error information, one has to call the GetLastError() function.
		/// Parameters of font_size, font_name and text_color are used for objects of OBJ_TEXT and OBJ_LABEL only. For objects of other types, these parameters are ignored
		/// </summary>
		/// <param name="name">Object name.</param>
		/// <param name="text">A text describing the object.</param>
		/// <param name="font_size">Font size in points.</param>
		/// <param name="font">Font name.</param>
		/// <param name="text_color">Text color.</param>
		/// <returns></returns>
		protected bool ObjectSetText(string name, string text, int font_size, string font = null,
		                             color text_color = new color())
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns total amount of objects of the specified type in the chart. 
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		protected int ObjectsTotal(int type = EMPTY)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Deletes object having the specified name. If the function succeeds, the returned value will be TRUE. Otherwise, it will be FALSE.
		/// To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		protected bool ObjectDelete(string name)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Search for an object having the specified name. The function returns index of the windows that contains the object to be found. If it fails, the returned value will be -1. To get the detailed error information, one has to call the GetLastError() function. The chart sub-windows (if there are sub-windows with indicators in the chart) are numbered starting from 1. The chart main window always exists and has the 0 index. 
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		protected int ObjectFind(string name)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function moves an object coordinate in the chart. Objects can have from one to three coordinates depending on their types. If the function succeeds, the returned value will be TRUE. Otherwise, it will be FALSE. To get the detailed error information, one has to call the GetLastError() function. The object coordinates are numbered starting from 0. 
		/// </summary>
		/// <param name="name"></param>
		/// <param name="point"></param>
		/// <param name="time1"></param>
		/// <param name="price1"></param>
		/// <returns></returns>
		protected bool ObjectMove(string name, int point, datetime time1, double price1)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function returns the object name by its index in the objects list. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="name"></param>
		/// <param name="point"></param>
		/// <param name="time1"></param>
		/// <param name="price1"></param>
		/// <returns></returns>
		protected string ObjectName(int index)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function returns the object type value. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		protected int ObjectType(string name)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Removes all objects of the specified type and in the specified sub-window of the chart. The function returns the count of removed objects. To get the detailed error information, one has to call the GetLastError() function.
		/// Notes: The chart sub-windows (if there are sub-windows with indicators in the chart) are numbered starting from 1. The chart main window always exists and has the 0 index. If the window index is missing or it has the value of -1, the objects will be removed from the entire chart.
		/// If the type value equals to -1 or this parameter is missing, all objects will be removed from the specified sub-window. 
		/// </summary>
		/// <param name="window"></param>
		/// <param name="type"></param>
		/// <returns></returns>
		protected int ObjectsDeleteAll(int window = 0, int type = 0)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The MessageBox function creates, displays, and operates message box. The message box contains an application-defined message and header, as well as a random combination of predefined icons and push buttons. If the function succeeds, the returned value is one of the MessageBox return code values.
		/// The function cannot be called from custom indicators since they are executed within interface thread and may not decelerate it. 
		/// </summary>
		/// <param name="text"></param>
		/// <param name="caption"></param>
		/// <param name="flags"></param>
		/// <returns></returns>
		protected int MessageBox(string text = "", string caption = "", int flags = 0)
		{
			return (int) System.Windows.Forms.MessageBox.Show(text, caption, (MessageBoxButtons) flags);
		}

		/// <summary>
		/// The MessageBox function creates, displays, and operates message box. The message box contains an application-defined message and header, as well as a random combination of predefined icons and push buttons. If the function succeeds, the returned value is one of the MessageBox return code values.
		/// The function cannot be called from custom indicators since they are executed within interface thread and may not decelerate it. 
		/// </summary>
		/// <param name="text"></param>
		/// <param name="flags"></param>
		/// <returns></returns>
		protected int MessageBox(string text = "", int flags = 0)
		{
			return (int) System.Windows.Forms.MessageBox.Show(text, "FDK", (MessageBoxButtons) flags);
		}

		/// <summary>
		/// Creation of an object with the specified name, type and initial coordinates in the specified window. Count of coordinates related to the object can be from 1 to 3 depending on the object type. If the function succeeds, the returned value will be TRUE. Otherwise, it will be FALSE. To get the detailed error information, one has to call the GetLastError() function. Objects of the OBJ_LABEL type ignore the coordinates. Use the function of ObjectSet() to set up the OBJPROP_XDISTANCE and OBJPROP_YDISTANCE properties.
		/// Notes: The chart sub-windows (if there are sub-windows with indicators in the chart) are numbered starting from 1. The chart main window always exists and has the 0 index.
		/// Coordinates must be passed in pairs: time and price. For example, the OBJ_VLINE object needs only time, but price (any value) must be passed, as well. 
		/// </summary>
		/// <param name="name">Object unique name.</param>
		/// <param name="type">Object type. It can be any of the Object type enumeration values.</param>
		/// <param name="window">Index of the window where the object will be added. Window index must exceed or equal to 0 and be less than WindowsTotal().</param>
		/// <param name="time1">Time part of the first point.</param>
		/// <param name="price1">Price part of the first point.</param>
		/// <param name="time2">Time part of the second point.</param>
		/// <param name="price2">Price part of the second point.</param>
		/// <param name="time3">Time part of the third point.</param>
		/// <param name="price3">Price part of the third point.</param>
		/// <returns></returns>
		protected bool ObjectCreate(string name, int type, int window, datetime time1, double price1,
		                            datetime time2 = new datetime(),
		                            double price2 = 0, datetime time3 = new datetime(), double price3 = 0)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The function returns the value of the specified object property. To check errors, one has to call the GetLastError() function. 
		/// See also ObjectSet() function. 
		/// </summary>
		/// <param name="name">Object name.</param>
		/// <param name="index">Object property index. It can be any of the Object properties enumeration values.</param>
		/// <returns></returns>
		protected double ObjectGet(string name, int index)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Changes the value of the specified object property. If the function succeeds, the returned value will be TRUE. Otherwise, it will be FALSE. To get the detailed error information, one has to call the GetLastError() function. 
		/// See also ObjectGet() function. 
		/// </summary>
		/// <param name="name">Object name.</param>
		/// <param name="index">Object value index. It can be any of Object properties enumeration values.</param>
		/// <param name="value">New value of the given property.</param>
		/// <returns></returns>
		protected bool ObjectSet(string name, int index, double value)
		{
			throw new NotImplementedException();
		}


		/// <summary>
		/// Closes opened order.
		/// </summary>
		/// <param name="ticket">unique number of the order ticket</param>
		/// <param name="lots">a closing volume in lots</param>
		/// <param name="price">ignored</param>
		/// <param name="slippage">ignored</param>
		/// <param name="Color"></param>
		/// <returns></returns>
		protected bool OrderClose(int ticket, double lots, double price, int slippage, int Color = CLR_NONE)
		{
			TradeRecord record = TradeRecordFromTicket(ticket);
			if (null == record)
			{
				return false;
			}
			try
			{
				SymbolInfo info = m_currentSnapshot.Symbols[record.Symbol];
				double volume = info.RoundLot*lots;

				if (AccountType.Gross == m_currentSnapshot.AccountInfo.Type)
				{
					ClosePositionResult result = record.ClosePartially(volume);
					SafeRefreshSnapshot();
					return result.Sucess;
				}
				else
				{
					if (!record.IsPosition)
					{
						return false;
					}

					TradeRecordSide side = (TradeRecordSide.Buy == record.Side) ? TradeRecordSide.Sell : TradeRecordSide.Buy;

					this.m_manager.Trader.Server.SendOrder(record.Symbol, TradeCommand.Market, side, 0, volume, null, null, null, null);
					SafeRefreshSnapshot();
					return true;
				}
			}
			catch (System.Exception ex)
			{
				Debug.WriteLine(ex);
				return false;
			}
		}

		/// <summary>
		/// Closes an opened order by another opposite opened order. If the function succeeds, the return value is true.
		/// </summary>
		/// <param name="ticket">unique number of the order ticket</param>
		/// <param name="opposite">unique number of the opposite order ticket.</param>
		/// <param name="Color"></param>
		/// <returns></returns>
		protected bool OrderCloseBy(int ticket, int opposite, int Color = CLR_NONE)
		{
			try
			{
				string firstOrderId = ticket.ToString(CultureInfo.InvariantCulture);
				string secondOrderId = opposite.ToString(CultureInfo.InvariantCulture);
				bool result = m_manager.Trader.Server.CloseByPositions(firstOrderId, secondOrderId);

				SafeRefreshSnapshot();

				return result;
			}
			catch (System.Exception ex)
			{
				Debug.WriteLine(ex);
				return false;
			}
		}

		/// <summary>
		/// Modification of characteristics for the previously opened position or pending orders.
		/// </summary>
		/// <param name="ticket">unique number of the order ticket</param>
		/// <param name="price">new open price of the pending order</param>
		/// <param name="stoploss">new StopLoss level</param>
		/// <param name="takeprofit">new TakeProfit level</param>
		/// <param name="expiration"></param>
		/// <param name="arrow_color"></param>
		/// <returns></returns>
		protected bool OrderModify(int ticket, double price, double stoploss, double takeprofit, datetime expiration,
		                           int arrow_color = CLR_NONE)
		{
			try
			{
				TradeRecord record = TradeRecordFromTicket(ticket);

				double? newActivationPrice = (price > 0) ? (double?) price : null;
				double? newStopLoss = (stoploss > 0) ? (double?) stoploss : null;
				double? newTakeProfit = (takeprofit > 0) ? (double?) takeprofit : null;
				DateTime? newExpiration = (expiration.Value > 0) ? (DateTime?) expiration.DateTime : null;
				record.Modify(newActivationPrice, newStopLoss, newTakeProfit, newExpiration);

				SafeRefreshSnapshot();

				return true;
			}
			catch (System.Exception)
			{
				return false;
			}
		}

		/// <summary>
		/// Returns close time for the currently selected order. If order close time is not 0 then the order selected and has been closed and retrieved from the account history. Open and pending orders close time is equal to 0.
		/// Note: The order must be previously selected by the OrderSelect() function. 
		/// </summary>
		/// <returns></returns>
		protected datetime OrderCloseTime()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Prints information about the selected order in the log in the following format:
		/// ticket number; open time; trade operation; amount of lots; open price; Stop Loss; Take Profit; close time; close price; commission; swap; profit; comment; magic number; pending order expiration date.
		/// Order must be selected by the OrderSelect() function. 
		/// </summary>
		protected void OrderPrint()
		{
			throw new NotImplementedException();
		}


		private void SafeRefreshSnapshot()
		{
			try
			{
				m_manager.RefreshSnapshot();
				m_currentSnapshot = m_manager.TakeSnapshot(m_symbol, m_priceType, m_periodicity);
			}
			catch (System.Exception)
			{
			}
		}

		private TradeRecord TradeRecordFromTicket(int ticket)
		{
			if ((null == m_currentSnapshot) || (null == m_currentSnapshot.TradeRecords))
			{
				return null;
			}
			string orderId = ticket.ToString(CultureInfo.InvariantCulture);
			foreach (var element in m_currentSnapshot.TradeRecords)
			{
				if (orderId == element.OrderId)
				{
					return element;
				}
			}
			return null;
		}

		private static void ConvertCmdToCommandAndSide(int cmd, out TradeCommand command, out TradeRecordSide side)
		{
			if (OP_BUY == cmd)
			{
				command = TradeCommand.Market;
				side = TradeRecordSide.Buy;
			}
			else if (OP_SELL == cmd)
			{
				command = TradeCommand.Market;
				side = TradeRecordSide.Sell;
			}
			else if (OP_BUYLIMIT == cmd)
			{
				command = TradeCommand.Limit;
				side = TradeRecordSide.Buy;
			}
			else if (OP_SELLLIMIT == cmd)
			{
				command = TradeCommand.Limit;
				side = TradeRecordSide.Sell;
			}
			else if (OP_BUYSTOP == cmd)
			{
				command = TradeCommand.Stop;
				side = TradeRecordSide.Buy;
			}
			else if (OP_SELLSTOP == cmd)
			{
				command = TradeCommand.Stop;
				side = TradeRecordSide.Sell;
			}
			else
			{
				string message = string.Format("Incorrect cmd = {0}");
				throw new ArgumentOutOfRangeException("cmd", cmd,
				                                      "Expected: OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT, OP_BUYSTOP or OP_SELLSTOP");
			}
		}

		#endregion

		#region statuses methods

		/// <summary>
		/// Returns true if the expert is allowed to trade, otherwise returns false.
		/// </summary>
		/// <returns></returns>
		protected bool IsTradeAllowed()
		{
			return true;
		}

		/// <summary>
		/// The method returns status of trade and feed connections.
		/// </summary>
		/// <returns>true, if the feed and trade are connected, otherwise false</returns>
		protected bool IsConnected()
		{
			bool result = false;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = snapshot.IsFeedLoggedOn && snapshot.IsTradeLoggedOn;
			}
			return result;
		}

		/// <summary>
		/// Returns true if the program (an expert or a script) has been commanded to stop its operation, otherwise returns false.
		/// </summary>
		/// <returns></returns>
		protected bool IsStopped()
		{
			return m_isStopped;
		}

		#endregion

		#region account information

		/// <summary>
		/// Returns free margin value of the current account.
		/// </summary>
		/// <returns>free margin value</returns>
		protected double AccountFreeMargin()
		{
			double result = 0;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = snapshot.AccountInfo.Equity - snapshot.AccountInfo.Margin;
			}
			return result;
		}

		/// <summary>
		/// Returns balance value of the current account (the amount of money on the account).
		/// </summary>
		/// <returns>equity value</returns>
		protected double AccountEquity()
		{
			double result = 0;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = snapshot.AccountInfo.Equity;
			}
			return result;
		}

		/// <summary>
		/// Returns margin value of the current account.
		/// </summary>
		/// <returns>margin value</returns>
		protected double AccountMargin()
		{
			double result = 0;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = snapshot.AccountInfo.Margin;
			}
			return result;
		}

		/// <summary>
		/// Returns profit value of the current account.
		/// </summary>
		/// <returns>profit value</returns>
		protected double AccountProfit()
		{
			double result = 0;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = snapshot.AccountInfo.Equity - snapshot.AccountInfo.Balance;
			}
			return result;
		}

		/// <summary>
		/// Returns balance value of the current account (the amount of money on the account).
		/// </summary>
		/// <returns>balance value</returns>
		protected double AccountBalance()
		{
			double result = 0;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = snapshot.AccountInfo.Balance;
			}
			return result;
		}

		/// <summary>
		/// Returns company name of the current account.
		/// </summary>
		/// <returns>account company</returns>
		protected string AccountCompany()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns  name of the current account.
		/// </summary>
		/// <returns>account name</returns>
		protected string AccountName()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns number of the current account.
		/// </summary>
		/// <returns>account number</returns>
		protected int AccountNumber()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns leverage of the current account.
		/// </summary>
		/// <returns>leverage value</returns>
		protected int AccountLeverage()
		{
			int result = 0;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = snapshot.AccountInfo.Leverage;
			}
			return result;
		}

		/// <summary>
		/// Returns the value of the Stop Out level.
		/// </summary>
		/// <returns>Stop Out level value</returns>
		protected int AccountStopoutLevel()
		{
			int result = 0;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = (int) Math.Round(snapshot.AccountInfo.StopOutLevel*100);
			}
			return result;
		}

		/// <summary>
		/// Returns free margin that remains after the specified position has been opened at the current price on the current account. If the free margin is insufficient, an error 134 (ERR_NOT_ENOUGH_MONEY) will be generated. 
		/// </summary>
		/// <param name="symbol"></param>
		/// <param name="cmd"></param>
		/// <param name="volume"></param>
		/// <returns></returns>
		protected double AccountFreeMarginCheck(string symbol, int cmd, double volume)
		{
			throw new NotImplementedException("AccountFreeMarginCheck");
		}

		#endregion

		#region string operations

		/// <summary>
		/// Search for a substring. Returns the position in the string from which the searched substring begins, or -1 if the substring has not been found.
		/// </summary>
		/// <param name="text">String to search in.</param>
		/// <param name="matched_text">Substring to search for.</param>
		/// <param name="start">Position in the string to start search from.</param>
		/// <returns></returns>
		protected static int StringFind(string text, string matched_text, int start = 0)
		{
			int result = text.IndexOf(matched_text, start);
			return result;
		}

		/// <summary>
		/// Extracts a substring from text string starting from the given position.
		/// The function returns a copy of the extracted substring if possible, otherwise, it returns an empty string. 
		/// </summary>
		/// <param name="text">String from which the substring will be extracted</param>
		/// <param name="start">Substring starting index. Can be from 0 to StringLen(text)-1.</param>
		/// <param name="length">Length of the substring extracted. If the parameter value exceeds or equals to 0 or the parameter is not specified, the substring will be extracted starting from the given position and up to the end of the string.</param>
		/// <returns></returns>
		protected static string StringSubstr(string text, int start, int length = 0)
		{
			return length == 0
				       ? text.Substring(start)
				       : text.Substring(start, length);
		}

		/// <summary>
		/// Returns character (code) from the specified position in the string. 
		/// </summary>
		/// <param name="text">String</param>
		/// <param name="pos">Char position in the string. Can be from 0 to StringLen(text)-1.</param>
		/// <returns></returns>
		protected static int StringGetChar(string text, int pos)
		{
			return text[pos];
		}


		/// <summary>
		/// The function cuts line feed characters, spaces and tabs in the left part of the string. The function returns a copy of the trimmed string, if possible. Otherwise, it returns an empty string. 
		/// </summary>
		/// <param name="text"></param>
		/// <returns></returns>
		protected static string StringTrimLeft(string text)
		{
			return text.TrimStart();
		}

		/// <summary>
		/// The function cuts line feed characters, spaces and tabs in the right part of the string. The function returns a copy of the trimmed string, if possible. Otherwise, it returns an empty string. 
		/// </summary>
		/// <param name="text"></param>
		/// <returns></returns>
		protected static string StringTrimRight(string text)
		{
			return text.TrimEnd();
		}

		/// <summary>
		/// Returns character count in a string. 
		/// </summary>
		/// <param name="text">String where the length must be calculated.</param>
		/// <returns></returns>
		protected static int StringLen(string text)
		{
			return text.Length;
		}




		#endregion

		#region styles

		/// <summary>
		/// The pen is solid.
		/// </summary>
		protected const int STYLE_SOLID = 0;

		/// <summary>
		/// The pen is dashed.
		/// </summary>
		protected const int STYLE_DASH = 1;

		/// <summary>
		/// The pen is dotted.
		/// </summary>
		protected const int STYLE_DOT = 2;

		/// <summary>
		/// The pen has alternating dashes and dots.
		/// </summary>
		protected const int STYLE_DASHDOT = 3;

		/// <summary>
		/// The pen has alternating dashes and double dots.
		/// </summary>
		protected const int STYLE_DASHDOTDOT = 4;

		#endregion

		#region service methods (part 2)

		/// <summary>
		/// The method always returns true.
		/// </summary>
		protected bool IsDllsAllowed()
		{
			return true;
		}

		/// <summary>
		/// The method always returns true.
		/// </summary>
		protected bool IsExpertEnabled()
		{
			return true;
		}

		/// <summary>
		/// The method always returns true.
		/// </summary>
		/// <returns></returns>
		protected bool IsDemo()
		{
			return true;
		}

		/// <summary>
		/// Returns TRUE if expert runs in the testing mode, otherwise returns FALSE. 
		/// </summary>
		/// <returns></returns>
		protected bool IsTesting()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Returns TRUE if expert runs in the strategy tester optimization mode, otherwise returns FALSE. 
		/// </summary>
		/// <returns></returns>
		protected bool IsOptimization()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// The method always returns zero.
		/// </summary>
		/// <returns></returns>
		protected int GetLastError()
		{
			return 0;
		}

		/// <summary>
		/// Gets the number of milliseconds elapsed since the system started.
		/// </summary>
		/// <returns></returns>
		protected int GetTickCount()
		{
			return Environment.TickCount;
		}

		/// <summary>
		/// The method returns address of trade server.
		/// </summary>
		/// <returns></returns>
		protected string AccountServer()
		{
			return string.Empty;
		}

		/// <summary>
		/// The Sleep() function suspends execution of the current expert within the specified interval.
		/// </summary>
		/// <param name="milliseconds"></param>
		protected void Sleep(int milliseconds)
		{
			Thread.Sleep(milliseconds);
		}

		/// <summary>
		/// Function plays a sound file. The file must be located in the terminal_dir\sounds directory or in its subdirectory. 
		/// </summary>
		/// <param name="filename">Path to the sound file.</param>
		protected void PlaySound(string filename)
		{
			using (var soundPlayer = new SoundPlayer(filename))
			{
				soundPlayer.Play(); // can also use soundPlayer.PlaySync()
			}
		}

		/// <summary>
		/// Returns the amount of minutes determining the used period (chart timeframe).
		/// </summary>
		/// <returns></returns>
		protected int Period()
		{
			if (BarPeriod.M1 == m_periodicity)
			{
				return PERIOD_M1;
			}
			if (BarPeriod.M5 == m_periodicity)
			{
				return PERIOD_M5;
			}
			if (BarPeriod.M15 == m_periodicity)
			{
				return PERIOD_M15;
			}
			if (BarPeriod.M30 == m_periodicity)
			{
				return PERIOD_M30;
			}
			if (BarPeriod.H1 == m_periodicity)
			{
				return PERIOD_H1;
			}
			if (BarPeriod.H4 == m_periodicity)
			{
				return PERIOD_H4;
			}
			if (BarPeriod.D1 == m_periodicity)
			{
				return PERIOD_D1;
			}
			if (BarPeriod.W1 == m_periodicity)
			{
				return PERIOD_W1;
			}
			if (BarPeriod.MN1 == m_periodicity)
			{
				return PERIOD_MN1;
			}
			string message = string.Format("Unsupported periodicity = {0}", m_periodicity);
			throw new Exception(message);
		}

		/// <summary>
		/// The method returns always zero.
		/// </summary>
		/// <param name="symbol">symbol name.</param>
		/// <param name="timeframe">Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe.</param>
		/// <returns></returns>
		protected int WindowHandle(string symbol, int timeframe)
		{
			return 0;
		}

		/// <summary>
		/// Returns currency name of the current account.
		/// </summary>
		/// <returns></returns>
		protected string AccountCurrency()
		{
			string result = null;
			Snapshot snapshot = m_currentSnapshot;
			if (null != snapshot)
			{
				result = snapshot.AccountInfo.Currency;
			}
			return result;
		}

		/// <summary>
		/// Returns credit value of the current account. 
		/// </summary>
		/// <returns>Credit value</returns>
		protected double AccountCredit()
		{
			throw new NotImplementedException();
		}

		#region Arrays

		/// <summary>
		/// Sets a new size for the first dimension.
		/// If executed successfully, it returns count of all elements contained in the array after resizing, 
		/// otherwise, returns -1, and array is not resized.
		/// </summary>
		/// <param name="array"></param>
		/// <param name="new_size"></param>
		/// <returns></returns>
		protected static int ArrayResize<T>(ref T[] array, int new_size)
		{
			Array.Resize(ref array, new_size);
			return new_size;
		}

		/// <summary>
		/// Returns the count of elements contained in the array. For a one-dimensional array, 
		/// the value to be returned by the ArraySize function is equal to that of ArrayRange(array,0). 
		/// </summary>
		/// <param name="array"></param>
		/// <returns></returns>
		protected static int ArraySize(Array array)
		{
			return array.Length;
		}

		/// <summary>
		/// Sets a new size for the first dimension.
		/// If executed successfully, it returns count of all elements contained in the array after resizing, 
		/// otherwise, returns -1, and array is not resized.
		/// </summary>
		/// <param name="array"></param>
		/// <param name="new_size"></param>
		/// <returns></returns>
		protected static void ArraySort<T>(T[] array)
		{
			Array.Sort(array);
		}

		#endregion

		#endregion

		#region service methods

		/// <summary>
		/// Rounds the floating point value to the given precision. Returns normalized value of the double type.
		/// </summary>
		/// <param name="value">a floating value</param>
		/// <param name="digits">must be from 0 to 8</param>
		/// <returns>normalized value</returns>
		protected static double NormalizeDouble(double value, int digits)
		{
			if ((digits < 0) || (digits > 8))
			{
				throw new ArgumentOutOfRangeException("digits", digits, "Digits precision must be from 0 to 8");
			}
			double factor = Math.Pow(10, digits);
			double result = value*factor;
			result = Math.Round(result);
			result /= factor;
			return result;
		}

		/// <summary>
		/// Prints a message to the console window. Parameters can be of any type.
		/// </summary>
		/// <param name="args">list of parameters, which should be printed</param>
		protected void Print(params object[] args)
		{
			Console.WriteLine(args);
		}

		/// <summary>
		/// Prints a message to the console window. Parameters can be of any type.
		/// </summary>
		/// <param name="args">list of parameters, which should be printed</param>
		protected void Alert(params object[] args)
		{
			Console.WriteLine(args);
		}

		/// <summary>
		/// Sends a message to the e-mail set in the Tools->Options->EMail tab.
		/// The sending can be disabled in settings, or it can be omitted to specify the e-mail address. To get the detailed error information, one has to call the GetLastError() function. 
		/// </summary>
		/// <param name="subject"></param>
		/// <param name="some_text"></param>
		protected void SendMail(string subject, string some_text)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sends the file to the FTP server set in the Tools->Options->Publisher tab. If the attempt fails, it retuns FALSE.
		/// The function does not operate in the testing mode. This function cannot be called from custom indicators, either.
		/// The file to be sent must be stored in the terminal_directory\experts\files folder or in its sub-folders.
		/// It will not be sent if there is no FTP address and/or access password specified in settings. 
		/// </summary>
		/// <param name="filename"></param>
		/// <param name="ftp_path"></param>
		/// <returns></returns>
		protected bool SendFTP(string filename, string ftp_path = null)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Sends Push notification to mobile terminals whose MetaQuotes IDs are specified on the "Notifications" tab in options window.
		/// Sending notifications can be disabled in the settings. The ID can also be omitted.
		/// In case of error, the function returns false. To get information about the error, call the GetLastError() function.
		/// 
		/// Note: The SendNotification() function has strict limitations on its usage: no more than 2 calls per second and no more than 10 calls per minute. Frequency of calls is controlled dynamically, and the function can be blocked in case of violation. 
		/// </summary>
		/// <param name="message"></param>
		/// <returns></returns>
		private bool SendNotification(string message)
		{
			throw new NotImplementedException();
		}

		#endregion

		#region math methods

		/// <summary>
		/// Returns text string with the specified numerical value converted into a specified precision format. 
		/// </summary>
		/// <param name="d">Floating point value.</param>
		/// <param name="decimals">Precision format, number of digits after decimal point (0-8).</param>
		/// <returns></returns>
		protected static string DoubleToStr(double d, int decimals)
		{
			var zeroes = string.Empty;
			for (var i = 0; i < decimals; i++)
				zeroes += "0";
			var format = string.Format("{{0:0.{0}}}", zeroes);
			var s = string.Format(format, d);
			return s;
		}

		/// <summary>
		/// Forms a string of the data passed and returns it. Parameters can be of any type. Amount of passed parameters cannot exceed 64.
		/// Parameters are transformed into strings according the same rules as those used in functions of Print(), Alert() and Comment(). The returned string is obtained as a result of concatenate of strings converted from the function parameters.
		/// The StringConcatenate() works faster and more memory-saving than when strings are concatenated using addition operations (+). 
		/// </summary>
		/// <param name="args"></param>
		/// <returns></returns>
		protected static string StringConcatenate(params object[] args)
		{
			return string.Join("", args);
		}

		/// <summary>
		/// The function outputs the comment defined by the user in the left top corner of the chart. Parameters can be of any type. Amount of passed parameters cannot exceed 64
		/// Arrays cannot be passed to the Comment() function. Arrays should be output element wise.
		/// Data of double type output with 4 digits after the decimal point. To output with more precision, use the DoubleToStr() function.
		/// Data of bool, datetime and color types will be output as their numeric presentation.
		/// To output values of datetime type as strings, convert them with the TimeToStr() function.
		/// See also Alert() and Print() functions.         /// </summary>
		/// <param name="args"></param>
		/// <returns></returns>
		protected static void Comment(params object[] args)
		{
			Debug.WriteLine(StringConcatenate(args));
		}

		/// <summary>
		/// Converts string representation of number to double type (double-precision format with floating point). 
		/// </summary>
		/// <param name="value">String containing the number character representation format..</param>
		/// <returns></returns>
		public static double StrToDouble(string value)
		{
			return Convert.ToDouble(value);
		}

		/// <summary>
		/// Converts string containing the value character representation into a value of the int (integer) type.  
		/// </summary>
		/// <param name="value">String containing the integer character representation format..</param>
		/// <returns></returns>
		protected static int StrToInteger(string value)
		{
			return Convert.ToInt32(value);
		}

		/// <summary>
		/// Conversion of the symbol code into a one-character string. 
		/// </summary>
		/// <param name="charCode"></param>
		/// <returns></returns>
		protected static string CharToStr(int charCode)
		{
			var ch = (char) charCode;
			return ch.ToString(CultureInfo.InvariantCulture);
		}

		/// <summary>
		/// Returns the absolute value of the specified numeric value.
		/// </summary>
		/// <param name="value">a numeric value</param>
		/// <returns>the absolute value</returns>
		protected static double MathAbs(double value)
		{
			return Math.Abs(value);
		}

		/// <summary>
		/// Returns the absolute value of the specified numeric value.
		/// </summary>
		/// <param name="value">a numeric value</param>
		/// <returns>the absolute value</returns>
		protected static int MathAbs(int value)
		{
			return Math.Abs(value);
		}

		/// <summary>
		/// The MathArccos function returns the arccosine of x within the range 0 to π (in radians).
		/// If x is less than -1 or exceeds 1, the MathArccos returns NaN (indeterminate value).
		/// </summary>
		/// <param name="x">value between -1 and 1 the arccosine of which to be calculated.</param>
		/// <returns></returns>
		protected static double MathArccos(double x)
		{
			return Math.Acos(x);
		}

		/// <summary>
		/// The MathArcsin function returns the arcsine of x in the range -π/2 to π/2 radians.
		/// If x is less than -1 or exceeds 1, the arcsine returns NaN (indeterminate value).
		/// </summary>
		/// <param name="x">value the arcsine of which to be calculated</param>
		/// <returns></returns>
		protected static double MathArcsin(double x)
		{
			return Math.Asin(x);
		}

		/// <summary>
		/// The MathArctan returns the arctangent of x.
		/// If x is 0, MathArctan returns 0. MathArctan returns a value within the range of -π/2 to π/2 radians.
		/// </summary>
		/// <param name="x">A number representing a tangent.</param>
		/// <returns></returns>
		protected static double MathArctan(double x)
		{
			return Math.Atan(x);
		}

		/// <summary>
		/// The MathCeil function returns a numeric value representing the smallest integer that exceeds or equals to x. 
		/// </summary>
		/// <param name="x">numeric value</param>
		/// <returns></returns>
		protected static double MathCeil(double x)
		{
			return Math.Ceiling(x);
		}

		/// <summary>
		/// Returns the cosine of the specified angle.
		/// </summary>
		/// <param name="value">An angle measured in radians.</param>
		/// <returns></returns>
		protected static double MathCos(double value)
		{
			return Math.Cos(value);
		}

		/// <summary>
		/// Returns the value of e raised to the power of d. At overflow, the function returns INF (infinity), and it returns 0 at underflow. 
		/// </summary>
		/// <param name="d">A number specifying the power.</param>
		/// <returns></returns>
		protected static double MathExp(double d)
		{
			return Math.Exp(d);
		}

		/// <summary>
		/// The MathFloor function returns a numeric value representing the largest integer that is less than or equal to x.
		/// </summary>
		/// <param name="x">a numeric value</param>
		/// <returns></returns>
		protected static double MathFloor(double x)
		{
			return Math.Floor(x);
		}

		/// <summary>
		/// The MathLog function returns the natural logarithm of x if successful.
		/// If x is negative, these functions return NaN (indeterminate value). If x is 0, they return INF (infinity).
		/// </summary>
		/// <param name="x">a value logarithm of which to be found</param>
		/// <returns></returns>
		protected static double MathLog(double x)
		{
			return Math.Log(x);
		}

		/// <summary>
		/// Returns the maximum value of two numeric values.
		/// </summary>
		/// <param name="value1">the first numeric value</param>
		/// <param name="value2">the second numeric value</param>
		/// <returns>maximum of two values</returns>
		protected static double MathMax(double value1, double value2)
		{
			return Math.Max(value1, value2);
		}

		/// <summary>
		/// Returns the maximum value of two numeric values.
		/// </summary>
		/// <param name="value1">the first numeric value</param>
		/// <param name="value2">the second numeric value</param>
		/// <returns>maximum of two values</returns>
		protected static int MathMax(int value1, int value2)
		{
			return Math.Max(value1, value2);
		}

		/// <summary>
		/// Returns the minimum value of two numeric values.
		/// </summary>
		/// <param name="value1">the first numeric value</param>
		/// <param name="value2">the second numeric value</param>
		/// <returns>minimum of two values</returns>
		protected static double MathMin(double value1, double value2)
		{
			return Math.Min(value1, value2);
		}

		/// <summary>
		/// Returns the minimum value of two numeric values.
		/// </summary>
		/// <param name="value1">the first numeric value</param>
		/// <param name="value2">the second numeric value</param>
		/// <returns>minimum of two values</returns>
		protected static int MathMin(int value1, int value2)
		{
			return Math.Min(value1, value2);
		}

		/// <summary>
		/// The function returns the floating-point remainder of division of two numbers.
		/// 
		/// The MathMod function calculates the floating-point remainder f  of x / y  such that x = i * y + f , where i  is an integer, f  has the same sign as x, and the absolute value of f  is less than the absolute value of y. 
		/// </summary>
		/// <param name="value"></param>
		/// <param name="value2"></param>
		/// <returns></returns>
		protected double MathMod(double value, double value2)
		{
			return (int) value%(int) value2;
		}

		/// <summary>
		/// Returns the value of the base expression raised to the specified power (exponent value).
		/// </summary>
		/// <param name="basis">base value</param>
		/// <param name="exponent">exponent value</param>
		/// <returns></returns>
		protected static double MathPow(double basis, double exponent)
		{
			return Math.Pow(basis, exponent);
		}

		/// <summary>
		/// The MathRand function returns a pseudorandom integer within the range of 0 to 32767
		/// </summary>
		/// <returns></returns>
		protected int MathRand()
		{
			return m_random.Next(1 + short.MaxValue);
		}

		/// <summary>
		/// Returns value rounded to the nearest integer of the specified numeric value.
		/// </summary>
		/// <param name="value">a numeric value to be rounded.</param>
		/// <returns></returns>
		protected static double MathRound(double value)
		{
			return Math.Round(value);
		}

		/// <summary>
		/// Returns the sine of the specified angle.
		/// </summary>
		/// <param name="value">an angle measured in radians</param>
		/// <returns></returns>
		protected static double MathSin(double value)
		{
			return Math.Sin(value);
		}

		/// <summary>
		/// The MathSqrt function returns the square root of x.
		/// If x is negative, MathSqrt returns an indefinite (same as a quiet NaN).
		/// </summary>
		/// <param name="x">positive numeric value</param>
		/// <returns></returns>
		protected static double MathSqrt(double x)
		{
			return Math.Sqrt(x);
		}

		/// <summary>
		/// The MathSrand() function sets the starting point for generating a series of pseudorandom integers.
		/// </summary>
		/// <param name="seed"></param>
		protected void MathSrand(int seed)
		{
			m_random = new Random(seed);
		}

		/// <summary>
		/// MathTan returns the tangent of x.
		/// If x is greater than or equal to 263, or less than or equal to -263, a loss of significance in the result occurs, in which case the function returns an indefinite (same as a quiet NaN).
		/// </summary>
		/// <param name="x">angle in radians</param>
		/// <returns></returns>
		protected static double MathTan(double x)
		{
			return Math.Tan(x);
		}

		#endregion

		#region advisers and symbols settings

		private string m_symbol;
		private PriceType m_priceType;
		private BarPeriod m_periodicity;
		private Manager m_manager;

		#endregion

		#region thread members

		private bool m_isStopped;
		private Thread m_thread;
		private readonly AutoResetEvent m_event = new AutoResetEvent(false);
		private MethodInfo m_init;
		private MethodInfo m_start;
		private MethodInfo m_deinit;

		#endregion

		#region snapshots

		private object m_synchronizer = new object();
		private Snapshot m_currentSnapshot;
		private Snapshot m_nextSnapshot;

		#endregion


		#region members

		private TradeRecord m_selectedTradeRecord;
		private Random m_random = new Random();

		#endregion
	}
}
